How to handle jodatime Illegal moment due to transition with time zone offset

I want to set joda DateTime for today at 2 a.m. (see code example below). But I get this exception:

 Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 2 for hourOfDay is not supported: Illegal instant due to time zone offset transition: 2011-03-27T02:52:05.239 (Europe/Prague) at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469) at org.joda.time.MutableDateTime.setHourOfDay(MutableDateTime.java:702) 

What is the correct way to throw a handle above or to create a DateTime at a specific hour of the day?

Code example:

 MutableDateTime now = new MutableDateTime(); now.setHourOfDay(2); now.setMinuteOfHour(0); now.setSecondOfMinute(0); now.setMillisOfSecond(0); DateTime myDate = now.toDateTime(); 

Thank.

+41
java jodatime
Mar 27 '11 at 18:01
source share
5 answers

It looks like you are trying to switch from a specific local time to an instance of DateTime , and you want it to be stable against summer savings. Try this ... (note that I am in the USA / East, so our transition date was March 13, 11, I had to find a suitable date to get the exception you got today. My updated code below is for CET, which moved on today.) The insight here is that Joda provides LocalDateTime so you can talk about setting up a local wall clock and whether it is legal in your time zone or not. In this case, I just add an hour if the time is not exists (your application must decide whether it is the right policy.)

 import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; class TestTz { public static void main(String[] args) { final DateTimeZone dtz = DateTimeZone.forID("CET"); LocalDateTime ldt = new LocalDateTime(dtz) .withYear(2011) .withMonthOfYear(3) .withDayOfMonth(27) .withHourOfDay(2); // this is just here to illustrate I'm solving the problem; // don't need in operational code try { DateTime myDateBorken = ldt.toDateTime(dtz); } catch (IllegalArgumentException iae) { System.out.println("Sure enough, invalid instant due to time zone offset transition!"); } if (dtz.isLocalDateTimeGap(ldt)) { ldt = ldt.withHourOfDay(3); } DateTime myDate = ldt.toDateTime(dtz); System.out.println("No problem: "+myDate); } } 

This code creates:

 Sure enough, invalid instant due to time zone offset transition!
 No problem: 2011-03-27T03: 00: 00.000 + 02: 00
+33
Mar 27 '11 at 18:15
source share

CET switches to daylight saving time (DST) on the last Sunday of March, which is today and today. Time went from 1:59:59 to 3:00:00 - there is no 2 there, so an exception.

You should use UTC instead of local time to avoid such a time zone problem.

 MutableDateTime now = new MutableDateTime(DateTimeZone.UTC); 
+12
Mar 27 '11 at 18:11
source share

I think a lot of the time, you'll want Joda to fix this automatically for you. You often don’t know the right way to correct the gap, because the size of the gap depends on the zone and year (although, of course, usually an hour).

One example of this is syntax analysis that comes from a source that you do not control; for example, networks. If the time stamp sender has stale zone files, this can happen. (If you have outdated zone files, you are very screwed up).

Here's a way to do this, which, provided, is a bit more complicated. I did this in joda 1.6 as well as 2.x since we ended up in 1.6 in our environment.

If you are building a date from some other inputs, as in your question, you can start with a UTC or LocalDate , as suggested above, and then adapt it to automatically correct the offset. A special sauce is in DateTimeZone.convertLocalToUTC

Dangerous:

 public DateTime parse(String str) { formatter.parseDateTime(gapdate) } 

Safe:

 public DateTime parse(String str) { // separate date from zone; you may need to adjust the pattern, // depending on what input formats you support String[] parts = str.split("(?=[-+])"); String datepart = parts[0]; DateTimeZone zone = (parts.length == 2) ? DateTimeZone.forID(parts[1]) : formatter.getZone(); // parsing in utc is safe, there are no gaps // parsing a LocalDate would also be appropriate, // but joda 1.6 doesn't support that DateTime utc = formatter.withZone(DateTimeZone.UTC).parseDateTime(datepart); // false means don't be strict, joda will nudge the result forward by the // size of the gap. The method is somewhat confusingly named, we're // actually going from UTC to local long millis = zone.convertLocalToUTC(utc.getMillis(), false); return new DateTime(millis, zone); } 

I tested this in the eastern and western hemispheres, as well as in the Lord Howe Island zone, which, as it turned out, was half an hour.

It would be nice if joda formatters supported setStrict (boolean), which would make them take care of this for you ...

+7
Jul 12 '13 at 4:13
source share

If you need to parse a date from a string:

 final DateTimeZone dtz = DateTimeZone.getDefault(); //DateTimeZone.forID("Europe/Warsaw") LocalDateTime ldt = new LocalDateTime("1946-04-14", dtz); if (dtz.isLocalDateTimeGap(ldt)){ ldt = ldt.plusHours(1); } DateTime date = ldt.toDateTime(); Date date = date.toDate(); 

Worked great for me. Maybe someone will need it.

+4
Dec 13 '16 at 14:01
source share

Update to jodatime 2.1 and use LocalDate.parse() :

 DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy"); LocalDate.parse(date, formatter); 
0
Oct. 13 '17 at 23:15
source share



All Articles