Control Timestamp precision of random timestamps - java

I've a code for generating random date strings. However I came to find that when I generate a random timestamp, it contains some precision decimal points to seconds field. How ever my SimpleDateFormat does not contain such precision values, does anyone know what is wrong here, and how can I remove or control the precision values ?
Code
long rangeBegin = Timestamp.valueOf("2015-01-01 00:00:00").getTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date currentDate = new Date();
String currentDateString = simpleDateFormat.format(currentDate);
long rangeEnd = Timestamp.valueOf(currentDateString).getTime();
long diff = rangeEnd - rangeBegin + 1;
Timestamp randomTimestamp = new Timestamp(rangeBegin + (long)(Math.random() * diff));
Sample output
randomTimestamp = 2015-02-20 02:36:00.646
Thanks
Edit :
String randomTimestampString = String.valueOf(randomTimestamp).split("\\.")[0];

The number after the decimal is for fractional precision, i.e. nanoseconds.
You could get rid of it by formatting or simply stripping them off using the String.substring() method.

randomTimestamp = 2015-02-20 02:36:00.646
According to the Timestamp javadoc this 646 means the nanoseconds for precision

Related

How to convert timestamp from GMT to Unix epoch

I'm parsing a timestamp which is "2022-01-12T17:17:34.512492+0000", this format is "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'ZZZZ" (ISO8601).
I want to convert it in epoch unix time, I'm using java.text.SimpleDateFormat.
I tried two methods but both don't work:
1- First Method
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'ZZZZ'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
Error showed:
java.text.ParseException: Unparseable date: "2022-01-12T17:17:34.512492+0000"
2- This second Method shows an output but is incorrect
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+0000'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
println(epoch)
Output:
1642004766492
If you convert this epoch to HUMAN DATE: "Wednesday, 12 January 2022 16:26:06.492"
The hours,minutes and seconds are wrong.
SimpleDateFormat is outdated, as Gael pointed out.
The Time API now supports up to nanoseconds, so microseconds are not an issue here. You should use DateTimeFormatter with ZonedDateTime. Your pattern is slightly wrong. Checking the docs for Offset Z:
Offset Z: This formats the offset based on the number of pattern
letters. One, two or three letters outputs the hour and minute,
without a colon, such as '+0130'. The output will be '+0000' when the
offset is zero. Four letters outputs the full form of localized
offset, equivalent to four letters of Offset-O. The output will be the
corresponding localized offset text if the offset is zero. Five
letters outputs the hour, minute, with optional second if non-zero,
with colon. It outputs 'Z' if the offset is zero. Six or more letters
throws IllegalArgumentException.
You can also print the time using toInstant to make sure it was parsed correctly:
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
val parsed = "2022-01-12T17:17:34.512492+0000"
val p = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZ"
val dtf = DateTimeFormatter.ofPattern(p)
val zdt = ZonedDateTime.parse(parsed, dtf)
println(zdt.toInstant) // 2022-01-12T17:17:34.512492Z
println(zdt.toInstant.toEpochMilli) // 1642004254512
Here is a nice article that explains in detail converting an ISO 8601 in Java. The comments at the end are particularly useful, as it shows the difference between the different patterns used.
looks like epoch has data in internal datetime format.
and you should convert it to string format
like this in java
public static String dateToString(Date d, String string_format) {
String result = "";
if(d != null) {
result = new SimpleDateFormat(string_format).format(d);
}
return result;
}
The timestamp you have has microseconds precision. Such precision is not supported by SimpleDateFormat. Also, Unix epoch time is usually up to milliseconds precision.
Possible solution here is to explicitly round the microseconds to milliseconds in the string before parsing, then use the yyyy-MM-dd'T'HH:mm:ss.SSSZ format.
String parsed = "2022-01-12T17:17:34.512492+0000";
String upToSeconds = parsed.substring(0, "yyyy-MM-ddTHH:mm:ss".length());
String microseconds = parsed.substring("yyyy-MM-ddTHH:mm:ss.".length(), "yyyy-MM-ddTHH:mm:ss.".length() + "SSSSSS".length());
String timezone = parsed.substring("yyyy-MM-ddTHH:mm:ss.SSSSSS".length());
String roundedMilliseconds = new BigDecimal(microseconds).divide(new BigDecimal("1000"), 0, RoundingMode.HALF_UP).toString();
String reformatted = upToSeconds + "." + roundedMilliseconds + timezone;
System.out.println(reformatted); // 2022-01-12T17:17:34.512+0000
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
long epoch = sdf.parse(reformatted).getTime();
System.out.println(epoch); // 1642007854512
System.out.println(Instant.ofEpochMilli(epoch)); // 2022-01-12T17:17:34.512Z

Calculate time difference in java

I want to calculate time difference in java. I am calculating successfully only in between 1 hour. When I enter the time above 1 hour calculation is getting Wrong.
String start= "12:00:00";
String end= "12:50:00";
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date date1 = format.parse(start);
Date date2 = format.parse(end);
long difference = date2.getTime() - date1.getTime();
System.out.println(difference/1000);
double time = difference/1000;
double tot = time/60;
JOptionPane.showMessageDialog(this, tot);
result displayed 50mins successfully from above code
I modified the same code and it looks like this:
String start = "12:00:00";
String end = "01:50:00";
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date date1 = format.parse(start);
Date date2 = format.parse(end);
long difference = date2.getTime() - date1.getTime();
System.out.println(difference/1000);
double time = difference/1000;
double tot = time/60;
JOptionPane.showMessageDialog(this, tot);
here result displayed
-610.0 I don't know why I need to display the output of 1.50
Because you input the time in the AM|PM form, but your code is supposed to work with the 24-hour time format.
Change the time from
String end = "01:50:00";
to
String end = "13:50:00";
and it will work like a charm :)
(Or you can change the code to work with AM-PM time model, but it will be more difficult.
Actually, I would use the new OffsetTime classes to solve this problem.
Here is some example code:
public static void distance(String strTime1, String strTime2) {
OffsetTime time1 = OffsetTime.parse(strTime1);
OffsetTime time2 = OffsetTime.parse(strTime2);
int time1Seconds = time1.get(ChronoField.MINUTE_OF_DAY);
int time2Seconds = time2.get(ChronoField.MINUTE_OF_DAY);
System.out.println("Time 1 in seconds: " + time1Seconds);
System.out.println("Time 1 in seconds: " + time2Seconds);
System.out.println("Distance: " + Math.abs(time1Seconds - time2Seconds));
}
What you are doing is to parse a String simliar to yours. As a difference, I would recommend you to always add timezone information. Since it probably doesn't matter much in your case, I'd just add +00:00.
Please not Maths.abs(). As long as you are interested in the distance between both times and not in which direction the distance is, you can use this to get rid of minus or plus prefixes and use the absolute value.
That way you can create OffsetTime by parsing this string. After that you can read the minute of the day.
Please try it with:
public static void main(String[] args) {
distance("10:00:00+00:00", "12:00:00+00:00");
distance("12:30:00+00:00", "12:31:00+00:00");
distance("12:31:00+00:00", "12:30:00+00:00");
}
The results would be:
Time 1 in seconds: 600
Time 1 in seconds: 720
Distance: 120
Time 1 in seconds: 750
Time 1 in seconds: 751
Distance: 1
Time 1 in seconds: 751
Time 1 in seconds: 750
Distance: 1
You mentioned that you need fractions of minutes, like 1.5. Fractions are always complicated and not precise. That's why people invented BigDecimal. However, in your case BigDecimal doesn't help. I would recommend you to use a smaller unit, like seconds.
Just change your code to:
int time1Seconds = time1.get(ChronoField.SECOND_OF_DAY);
int time2Seconds = time2.get(ChronoField.SECOND_OF_DAY);
Here is some Javadocs:
https://docs.oracle.com/javase/8/docs/api/index.html?java/time/LocalDateTime.html
And a tutorial to the new classes (JDK8):
https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html
From SimpleDateFormat
Letter | Date or Time Component
H | Hour in day (0-23) .
h | Hour in am/pm (1-12)
So in your case you have "HH:mm:ss" which stands for 24Hr time format.
and its start from 00:00 till 23:59
So you can change this to like below for above pattern:
String start = "12:00:00";
String end = "13:50:00";
Or you can change your pattern like below:
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
String start = "12:00:00";
String end = "01:50:00";
See result: code output

Convert String "01-09-2015' to Long - Java/Android

Hi I have a String like this "01-09-2015"
I need to convert this string to long.
I have tried using
String date = "01-09-2015";
Long dateLong = Long.getLong(date);
Long dateLong = Long.valueOf(date);
Long dateLong = Long.valueOf(date,36);
Long dateLong = Long.parseLong(date);
Still no help. Everything returns be NumberFormatException.
Anyone please help.
Thanks in advance.
EDIT
Guys, I will send in a String, which is of course a date like "08-01-2015". For each unique string which I pass, I need a unique long value. Thats all.
You have to convert it to Date first before changing it to Long
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yy");
Date d = format.parse("01-09-2015");
long milliseconds = d.getTime();
I recommend you split the input on -, then convert the three date parts to int; and then concatenate them into a long. Something like,
String date = "01-09-2015";
String[] arr = date.split("-");
int yyyy = Integer.valueOf(arr[2]);
int mm = Integer.valueOf(arr[0]);
int dd = Integer.valueOf(arr[1]);
long dateLong = (yyyy * 10000) + (mm * 100) + dd;
System.out.println(dateLong);
Output is (the unique, per date)
20150109
Note This is in keeping with ISO 8601; the linked Wikipedia article says (in part)
ISO 8601 Data elements and interchange formats – Information interchange – Representation of dates and times is an international standard covering the exchange of date and time-related data.

How can i format a decimal value into hours and minutes?

for example if the user input is 1.71 (1 hour and 71 minutes), then i want to convert it to 2.11 (2 hours and 11 minutes)
DecimalFormat time = new DecimalFormat("##.## p.m");
int userInput = 1.71;
System.out.print(time.format(userInput));
Parse the input as date and than format the date to your output format:
Scanner sc = new Scanner(System.in);
DateFormat df = new SimpleDateFormat("HH.mm");
DateFormat dfout = new SimpleDateFormat("H.mm a");
Date date = df.parse(sc.next());
System.out.println(dfout.format(date));
I'm not sure whether I get your question right, but shouldn't the following work?
int hours = (int)userInput;
decimal minutestmp = ((userInput - hours) * 60);
int minutes = (int)minutestmp;
String TimeString = hours + ":" + minutes;
Date date = new SimpleDateFormat("HH:mm").parse(TimeString);
String newTimeString = new SimpleDateFormat("H:mm").format(date);
ISO 8601
The ISO 8601 standard for date-time strings defines a format for what they call Durations: PnYnMnDTnHnMnS.
Joda-Time
The Joda-Time library knows how to parse and generate such strings.
So first, transform your input into such a string. Then feed that new string into Joda-Time. Lastly ask Joda-Time to recalculate the hours and minutes. All of this has been covered on StackOverflow multiple times. Please search for details.
To translate that input, replace the period, and prepend and append.
String d = "PT" + "1.71".replace( ".", "H") + "M"; // PT1H71M
Feed to Joda-Time.
Period period = Period.parse( d );
Normalize the minutes.
Period p = period.normalizedStandard();
Alternatively, you could tear apart the hours and minutes portions of your input, then feed them as ints to a constructor of Period.

Is it possible to get timestamp format 'dd-MM-yyyy HH:mm:ss.SSS.xxxxxx.nnnnnnnnn' in java? [duplicate]

This is my code:
long currentTime = System.currentTimeMillis();
Date date = new Date(currentTime); // if you really have long
String result = new SimpleDateFormat("HH:mm:ss").format(date.getTime());
Is it possible to add milliseconds and nanoseconds to the date format ?
You can add milliseconds by adding SSS at the end, such as the format will be HH:mm:ss.SSS.
There is no reference in the SimpleDateFormat to nanoseconds. Usually System.nanoTime() is used for performance debugging and not for display purposes.
String result = new SimpleDateFormat("HH:mm:ss:SSS").format(date);
"HH:mm:ss:SSS" //SSS stands for milliseconds
Check SimpleDateFormat API for more info
String timeStamp = new SimpleDateFormat("dd:MM:yyyy_HH:mm:ss:SSS").format(Calendar.getInstance().getTime());
timeStamp = timeStamp + ":" + System.nanoTime();
This gave me output,
24:03:2014_18:24:09:890:2018826751601473

Categories