Hours difference while considering the date - java

I need to extract the date field from DB and store it in a VO. How can I compare the hours difference from two dates.
For ex:
Let's say date1 = 01-SEP-17 10:00:00 and date2 = 05-SEP-17 12:00:00. I need to compare the two dates and perform some operations like:
if(hours>10){
//do something
}
if(hours<10){
//do something else
}
I'm just able to calculate the difference between the hours (date2-date1) as 2 but how to consider the date too while calculating the difference between the hours?
My present code:
Date dateA = someVO.getDate();
long date = System.currentTimeMillis();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-YY HH:mm:ss");
Date date1 = new Date(date);
Date date2 = df.parse(dateA.toString());
long date1Hours = date1.getHours();
long date2Hours = date2.getHours();
long dateDiff = date1Hours-date2Hours;
if(dateDiff>10){
//something
}
else if(dateDiff<10){
//something else
}

Easy enough to do using the new Java-Time API added in Java 8:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd-MMM-yy HH:mm:ss")
.toFormatter(Locale.US);
LocalDateTime date1 = LocalDateTime.parse("01-SEP-17 10:00:00", fmt);
LocalDateTime date2 = LocalDateTime.parse("05-SEP-17 12:00:00", fmt);
long hours = ChronoUnit.HOURS.between(date1, date2);
System.out.println(hours);
Output
98

First you need to change the pattern used in SimpleDateFormat, and also use a java.util.Locale to specify that the month name is in English (otherwise it uses the system default locale, and it's not guaranteed to always be English).
Then you get the correspondent millis value of each Date, calculate the difference between them and convert this to hours, using a java.util.concurrent.TimeUnit:
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yy HH:mm:ss", Locale.ENGLISH);
Date date1 = df.parse("01-SEP-17 10:00:00");
Date date2 = df.parse("05-SEP-17 12:00:00");
// get the difference in hours
long dateDiff = TimeUnit.MILLISECONDS.toHours(date2.getTime() - date1.getTime());
dateDiff will be 98.
If you want to compare with the current date, just use new Date().
Daylight Saving Time issues
There's one problem with this approach. Although it doesn't make a difference for most part of the year, there can be differences due to Daylight Saving Time changes.
By default, SimpleDateFormat uses the JVM default timezone. If between the 2 dates there's a Daylight Saving Time changeover (or just an offset change), the result might be different.
Example: in Africa/Windhoek timezone, in September 3rd 2017, at 2 AM, clocks shifted 1 hour forward, from 2 AM to 3 AM (and the offset changed from +01:00 to +02:00). This means that, at that day, all local times between 2 AM and 2:59 AM don't exist in this timezone (it's like they "skipped" this hour).
So, if the JVM default timezone is Africa/Windhoek, then the difference using the code above will be 97 hours (and not 98).
Even if your JVM default timezone is not Africa/Windhoek, this can still happen, depending on the timezone and the dates involved.
Not only that, but the default timezone can be changed without notice, even at runtime. It's always better to specify which timezone you're working with instead of just relying on the default.
You can't avoid DST effects (unless you use UTC), but at least you can choose which timezone you're going to use instead of relying on the system default (that can be changed without notice).
It's possible to set a timezone in the formatter, so all dates will be parsed taking this timezone into account. In the example below, I'm using Europe/London, but of course you can change to one that best suits your case:
// set Europe/London timezone in the SimpleDateFormat
df.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Now all the parsed dates will be considered to be in London timezone (but remind that DST effects will still be considered - the advantage is that you know what timezone you're using and any changes in the JVM's default won't make your code suddenly start giving different and unexpected results).
Always use IANA timezones names (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of all timezones using TimeZone.getAvailableIDs() - then you can choose the one that best suits your case.
If you don't want to consider DST effects, you can use TimeZone.getTimeZone("UTC") - because UTC is a standard without DST changes.
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
First you need to parse the inputs (using a DateTimeFormatter) and specify in what timezone they are. As the dates also have a timezone, I'm using a ZonedDateTime, which is the best choice for this case.
Then you can easily calculate the difference in hours using a ChronoUnit. In the example below, I'm also using London timezone as an example:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive for month name in all caps
.parseCaseInsensitive()
// date/time pattern
.appendPattern("dd-MMM-yy HH:mm:ss")
// use English locale for month name
.toFormatter(Locale.ENGLISH)
// set a timezone
.withZone(ZoneId.of("Europe/London"));
// parse the dates
ZonedDateTime z1 = ZonedDateTime.parse("01-SEP-17 10:00:00", fmt);
ZonedDateTime z2 = ZonedDateTime.parse("05-SEP-17 12:00:00", fmt);
// calculate the difference in hours
long diffHours = ChronoUnit.HOURS.between(z1, z2);
If you want to use UTC, just change the ZoneId to ZoneOffset.UTC constant. If you want to compare with the current date, just use:
// use the same ZoneId used in the formatter if you want to consider DST effects
ZonedDateTime.now(ZoneId.of("Europe/London"));
Conversions to/from Date
If you still need to work with java.util.Date, it's possible to convert from/to the new API. In Java 8 you can use native methods, and in Java <=7 the ThreeTen Backport has the org.threeten.bp.DateTimeUtils class.
To convert a Date to the new classes:
Date date = // java.util.Date
// convert to zoneddatetime (java 8)
ZonedDateTime z = date.toInstant().atZone(ZoneId.of("Europe/London"));
// convert to zoneddatetime (java 7 ThreeTen Backport)
ZonedDateTime z = DateTimeUtils.toInstant(date).atZone(ZoneId.of("Europe/London"));
To convert a ZonedDateTime back to a date:
// convert to zoneddatetime (java 8)
Date date = Date.from(z.toInstant());
// convert to zoneddatetime (java 7 ThreeTen Backport)
Date date = DateTimeUtils.toDate(z.toInstant());

You've essentially already got the times in milliseconds. You could always just compare the milliseconds directly instead.
long tenHoursInMillis = 36000000;
long dateVOMillis = someVO.getDate().getTime();
long dateSysMillis = System.currentTimeMillis();
if(dateSysMillis - dateAMillis > tenHoursInMillis) {
// do something
}
else if(dateSysMillis - dateAMillis < tenHoursInMillis) {
// do something else
}
// do something when they're equal

Related

Convert from Millisecond to String of Date

I try to convert from Milliseconds to string of date. However, the result is not correct as my expected.
The input is milliseconds (Ex: 1508206600485)
My time zone is UTC +10:00
------Expected-------------------------------------------- Actual------
01:32 (PM) 17/10/2017--------------------------------02:32 (PM) 17/10/2017
Here is the method of that
public static String getDate(long milliSeconds) {
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm dd/MM/yyyy");
String dateString = formatter.format(new Date(milliSeconds));
return dateString;
}
Good you found a solution, I just like to add an approach with Java 8 new java.time API. The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and it's strongly recommended to switch to the new API if possible.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
To convert the millis value to a specific timezone, you can use the Instant class, then use a ZoneId to convert to a timezone, creating a ZonedDateTime.
Then you use a DateTimeFormatter to format it:
// convert millis value to a timezone
Instant instant = Instant.ofEpochMilli(1508206600485L);
ZonedDateTime z = instant.atZone(ZoneId.of("Australia/Sydney"));
// format it
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("hh:mm dd/MM/yyyy");
System.out.println(fmt.format(z)); // 01:16 17/10/2017
The output is:
01:16 17/10/2017
Note that I used hh for the hours. According to javadoc, this lettern represents the clock-hour-of-am-pm field (values from 1 to 12), so without the AM/PM indicator, it can be ambiguous. Maybe you want to add AM/PM field (adding the letter a to the format pattern), or change the hours to HH (hour-of-day, with values from 0 to 23).
Also note that the actual value of the ZonedDateTime is 2017-10-17T13:16:40.485+11:00 (01:16 PM), because in October 17th 2017, Sydney is in Daylight Saving Time, so the actual offset is +11:00.
Basing on #phlaxyr, I have solved my problem. You can get your time zone in this link below
http://tutorials.jenkov.com/java-date-time/java-util-timezone.html
public static String getDate(long milliSeconds) {
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm dd/MM/yyyy");
formatter.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
String dateString = formatter.format(new Date(milliSeconds));
return dateString;
}

Java - SimpleDateFormat formatter to return epoch time with milliseconds [duplicate]

This question already has answers here:
Convert a date format in epoch
(6 answers)
Closed 5 years ago.
I am very new to Java and coding in general - I have some code which returns a timestamp in the following format yyyy.MM.dd HH:mm:ss:ms which is shown below:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
This returns:
2017.07.19 11:42:30:423
Is there a way to edit the "SimpleDateFormat formatter" code above to return the date/time as an epoch timestamp that includes milliseconds so that the value returned is formatted as per the below?
1500464550423
I'm hoping that I can amend the ("yyyy.MM.dd HH:mm:ss:sss") part of the SimpleDateFormat formatter code to do this.
Any help or advice is much appreciated.
Thanks
You have a simple error in the use of case in your format pattern string (these are case sensitive). And worse, you are using the old and troublesome SimpleDateFormat class. One of the many problems with it is it’s not telling you what the problem is.
So I recommend you use the modern Java date and time API instead (I am deliberately using your format pattern string verbatim):
String receivedTimetamp = "2017.07.19 11:42:30:423";
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:sss");
LocalDateTime dateTime = LocalDateTime.parse(receivedTimetamp, parseFormatter);
System.out.println(dateTime);
This code throws an IllegalArgumentException: Too many pattern letters: s. I hope this calls your awareness to the fact that you are using two s’s for seconds and three s’s for fraction of second. If it still isn’t clear, the documentation will tell you that lowercase s is correct for seconds, while you need uppercase S for the fraction. Let’s repair:
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
Now the code prints 2017-07-19T11:42:30.423, so we have managed to parse the string correctly.
To convert to milliseconds we are still missing a crucial piece of information: in what time zone should the timestamp be interpreted? I think the two obvious guesses are UTC and your local time zone (which I don’t know). Try UTC:
System.out.println(dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli());
This produces 1500464550423, which is the number you asked for. I suppose we’re done.
If you wanted your JVM’s time zone setting instead, use .atZone(ZoneId.systemDefault()) instead of .atOffset(ZoneOffset.UTC), but beware that the setting may be altered by other software running in the same JVM, so this is fragile.
First of all, check the documentation of SimpleDateFormat. The pattern that corresponds to milliseconds is an uppercase S, while the lowercase s corresponds to seconds. The problem is that SimpleDateFormat usually doesn't complain and try to parse 423 as seconds, adding this amount to your end date (giving an incorrect result).
Anyway, SimpleDateFormat just parses a String to a java.util.Date or formats the Date to a String. If you want the epoch millis value, you must get it from the Date object:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
// parse to a date
Date date = formatter.parse(s);
// get epoch millis
long millis = date.getTime();
System.out.println(millis); // 1500475350423
The problem is that SimpleDateFormat uses the system's default timezone, so the final value above (1500475350423) will be equivalent to the specificed date and time in my system's timezone (which can be different from yours - just for the record, my system's default timezone is America/Sao_Paulo). If you want to specify in what timezone this date is, you need to set in the formatter (before calling parse):
// set a timezone to the formatter (using UTC as example)
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
With this, the result for millis will be 1500464550423 (the equivalent to the specificed date and time in UTC).
To do the opposite (create a date from the millis value), you must create a Date object and then pass it to the formatter (also taking care of setting a timezone to the formatter):
// create date from millis
Date date = new Date(1500464550423L);
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// format date
String formatted = formatter.format(date);
Java new date/time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
As the input String has no timezone information (only date and time), first I parsed it to a LocalDateTime (a class that represents a date and time without timezone). Then I convert this date/time to a specific timezone and get the millis value from it:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// as the input string has no timezone information, parse it to a LocalDateTime
LocalDateTime dt = LocalDateTime.parse(s, formatter);
// convert the LocalDateTime to a timezone
ZonedDateTime zdt = dt.atZone(ZoneId.of("Europe/London"));
// get the millis value
long millis = zdt.toInstant().toEpochMilli(); // 1500460950423
The value is now 1500460950423, equivalent to the specified date and time in London timezone.
Note that the API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
You can also use ZoneOffset.UTC constant if you want to use UTC.
To do the opposite, you can get the millis value to create an Instant, convert it to a timezone and pass it to the formatter:
// create Instant from millis value
Instant instant = Instant.ofEpochMilli(1500460950423L);
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// convert to timezone
ZonedDateTime z = instant.atZone(ZoneId.of("Europe/London"));
// format
String formatted = z.format(formatter);
First advice is to move to java8 java.time API instead of learning the broken java.date API
then do:
Instant i = Instant.now();
System.out.println(i.toEpochMilli());
in your case you can do:
LocalDateTime myldt = LocalDateTime.parse("2017-06-14 14:29:04",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(myldt.toInstant(ZoneOffset.UTC).toEpochMilli());
note that as soon as you play more with the api you will find more ways to achieve the same thing, at the end you will end invoking toEpochMilli
String strDate = "Jun 13 2003 23:11:52.454 UTC";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss.SSS zzz");
ZonedDateTime zdt = ZonedDateTime.parse(strDate,dtf);
System.out.println(zdt.toInstant().toEpochMilli()); // 1055545912454
You can try
long time = System.currentTimeMillis();
If you have a java.util.Date then invoking getTime() will return the number of millis since the epoch. For example:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
Date dateToBeFormatted = new Date();
// this will print a datetime literal on the above format
System.out.println(formatter.format(dateToBeFormatted));
// this will print the number of millis since the Java epoch
System.out.println(dateToBeFormatted.getTime());
The key point here is that in order to get the number of millis since the epoch you do not need a SimpleDateFormatter because the number of millis since the epoch is a property of the Date.

Jboss Java Date daylight saving time

Have an issue where, when clocks are moved due to a Daylight savings time (twice a year), dates are not correct in Java (I am based in Central Europe: GMT+2 in summer, GMT+1 in winter)
If time is moved 1 hour ahead, new Date() still returns old time (1 hour behind of current time).
In Java 7, can this be solved, without restarting the Jboss application servers?
If I change the time manually in Windows, reproduce the problem: Date is not updated to the system date unless jboss is restarted.
Calendar c = Calendar.getInstance();
c.setTime(new Date());
In Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes.
With this, you can handle DST changes easily.
First, you can use the org.threeten.bp.DateTimeUtils to convert from and to Calendar.
The following code converts the Calendar to org.threeten.bp.Instant, which is a class that represents an "UTC instant" (a timestamp independent of timezone: right now, at this moment, everybody in the world are in the same instant, although their local date and time might be different, depending on where they are).
Then, the Instant is converted to a org.threeten.bp.ZonedDateTime (which means: at this instant, what is the date and time at this timezone?). I also used the org.threeten.bp.ZoneId to get the timezone:
Calendar c = Calendar.getInstance();
c.setTime(new Date());
// get the current instant in UTC timestamp
Instant now = DateTimeUtils.toInstant(c);
// convert to some timezone
ZonedDateTime z = now.atZone(ZoneId.of("Europe/Berlin"));
// today is 08/06/2017, so Berlin is in DST (GMT+2)
System.out.println(z); // 2017-06-08T14:11:58.608+02:00[Europe/Berlin]
// testing with a date in January (not in DST, GMT+1)
System.out.println(z.withMonth(1)); // 2017-01-08T14:11:58.608+01:00[Europe/Berlin]
I've just picked some timezone that uses Central Europe timezone (Europe/Berlin): you can't use those 3-letter abbreviations, because they are ambiguous and not standard. You can change the code to the timezone that suits best for your system (you can get a list of all available timezones with ZoneId.getAvailableZoneIds()).
I prefer this solution because it's explicit what timezone we're using to display to the user (Date and Calendar's toString() methods use the default timezone behind the scenes and you never know what they're doing).
And internally, we can keep using the Instant, which is in UTC, so it's not affected by timezones (and you can always convert to and from timezones whenever you need) - if you want to convert the ZonedDateTime back to an Instant, just use the toInstant() method.
Actually, if you want to get the current date/time, just forget the old classes (Date and Calendar) and use just the Instant:
// get the current instant in UTC timestamp
Instant now = Instant.now();
But if you still need to use the old classes, just use DateTimeUtils to do the conversions.
The output of the examples above are the result of the ZonedDateTime.toString() method. If you want to change the format, use the org.threeten.bp.format.DateTimeFormatter class (take a look at the javadoc for more details about all the possible formats):
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z X");
// DST (GMT+02)
System.out.println(formatter.format(z)); // 08/06/2017 14:11:58 CEST +02
// not DST (GMT+01)
System.out.println(formatter.format(z.withMonth(1))); // 08/01/2017 14:11:58 CET +01
Use ZonedDateTime class from JDK 8 java.time. It accommodates the Daylight Saving Time changes.
Refer the details at : https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html

Converting String to time, changing the timezone, then back to String

I have a String containing a time in the format: 08:00:00
This time is from US Eastern time and I want to convert it to London's timezone and end up with a String of that time.
I have converted the String to time using
Time.valueOf(t);
However after this I cannot get the timezone to change.
you can displace the time using withZoneSameInstant
LocalTime myLocalTime = LocalTime.parse("08:00:00", DateTimeFormatter.ofPattern("HH:mm:ss"));
LocalTime londonTime = LocalDateTime.of(LocalDate.now(), myLocalTime).atZone(ZoneId.of("America/New_York"))
.withZoneSameInstant(ZoneId.of("Europe/London")).toLocalTime();
System.out.println(myLocalTime);
System.out.println(londonTime);
There are lots of details regarding this question.
The Time class sets the date (day, month and year) to January 1st, 1970. But to convert from EST to London local time, you must consider Daylight Saving Time rules.
The difference in hours is not always the same; it can change depending on the date - considering this year (2017): from January 1st to March 11th, the difference will be 5 hours, then from March 12th to March 25th the difference is 4 hours, then it's back to 5 hours, then in October 29th it's 4 hours and in November 5th is 5 hours again, until the end of the year.
That's because of DST starting and ending in both timezones and at different dates. And each year, these dates change as well, so you need to know the date you're working with, to make the correct conversion.
Another thing is that Java 8 new API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or EST) because they are ambiguous and not standard.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
In the example below I'm using America/New_York - one of the many timezones that uses EST (there are more than 30 timezones that uses or had used it). You can call ZoneId.getAvailableZoneIds() to check all the timezones and choose one that suits best for your case.
The code is very similar to #ΦXocę 웃 Пepeúpa ツ answer, well, because it's straightforward and there's not much to change. I just wanted to add the insights above.
// timezones for US and UK
ZoneId us = ZoneId.of("America/New_York");
ZoneId uk = ZoneId.of("Europe/London");
// parse the time string
LocalTime localTimeUS = LocalTime.parse("08:00:00");
// the reference date (now is the current date)
LocalDate now = LocalDate.now(); // or LocalDate.of(2017, 5, 20) or any date you want
// the date and time in US timezone
ZonedDateTime usDateTime = ZonedDateTime.of(now, localTimeUS, us);
// converting to UK timezone
ZonedDateTime ukDateTime = usDateTime.withZoneSameInstant(uk);
// get UK local time
LocalTime localTimeUK = ukDateTime.toLocalTime();
System.out.println(localTimeUK);
The output will be 13:00 (the result of localTimeUK.toString()) because toString() omits the seconds if the value is zero.
If you want to always output the seconds, you can use a DateTimeFormatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss");
String time = fmt.format(localTimeUK);
In this case, the string time will be 13:00:00.
LocalDate.now() returns the current date using your system's default timezone. If you want the current date in a specific zone, you could've called LocalDate.now(us) (or anyzone you want, or even explicit use the default: LocalDate.now(ZoneId.systemDefault()))

SimpleDateFormat to java.time

I'm trying to understand how the Java 8 date/time framework works.
I'm actually using SimpleDateFormat this way to return milliseconds given a string:
new SimpleDateFormat("yyyyMMddHHmmssSSS").parse(builder.toString()).getTime();
What would it become with the new classes in Java 8?
The pattern you specified cannot work in Java-8. The problem has been fixed in Java-9 with seemingly no backport, but Java-9 is not yet released.
Possible workarounds for Java-8 either include awkward string preprocessing, that is inserting a decimal separator before the fraction part or downloading other 3rd-party-libraries (where the parsers are probably still quicker than in Java-9 according to my observations):
String preprocessing
String mydate = "20130812214600025";
String adjustedInput = new StringBuilder(mydate).insert(14, '.').toString();
ZonedDateTime date =
ZonedDateTime.parse(
adjustedInput,
DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSS").withZone(ZoneOffset.systemDefault()));
System.out.println(date); // 2013-08-12T21:46:00.025+02:00[Europe/Berlin]
System.out.println(date.toInstant().toEpochMilli()); // 1376336760025
Joda-Time:
String mydate = "20130812214600025";
DateTime date =
DateTime.parse(
mydate,
DateTimeFormat.forPattern("yyyyMMddHHmmssSSS"));
System.out.println(date); // 2013-08-12T21:46:00.025+02:00
System.out.println(date.toInstant().getMillis()); // 1376336760025
My library Time4J
long millisSinceUnix =
ChronoFormatter.ofPattern(
"yyyyMMddHHmmssSSS",
PatternType.CLDR,
Locale.ROOT,
Moment.axis(TemporalType.MILLIS_SINCE_UNIX)
).with(Timezone.ofSystem()).parse(mydate).longValue();
System.out.println(millisSinceUnix); // 1376336760025
For your information: The timezone is needed because we convert local details like year, month, day, hour etc to a global instant but your input does not contain any zone or offset information. Therefore it is necessary to supply the formatter with a zone or offset.
As you can see, SimpleDateFormat and Joda-Time use the system timezone by default (implicitly). However, the java.time-API and Time4J require to explicitly specify a timezone (IMHO the cleaner design).
You can use:
ZonedDateTime date = ZonedDateTime.parse("mydate",DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
System.out.println(date.toInstant().toEpochMilli());

Categories

Resources