I am writing some code to do periodic scheduling based based on time of day. I am representing the regular schedule time of day as a Joda LocalTime
object. I then create event instances by converting the LocalTime
to a DateTime
. When initially writing the code (and only scheduling events for "today") I used the toDateTimeToday()
method on LocalTime
and it worked as expected. However when I switched to using the toDateTime()
method to schedule events in the future I started seeing issues with mapping between UTC and local local timezone.
The following code demonstrates the problem I am seeing.
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
LocalTime lt = new LocalTime(12,0);
System.out.println(" lt="+lt);
DateTime dtt = lt.toDateTimeToday();
System.out.println("dtt="+df.format(dtt.toDate()));
DateTime bdt = new DateTime();
System.out.println("bdt="+df.format(bdt.toDate()));
DateTime dt = lt.toDateTime(bdt.toInstant());
System.out.println(" dt="+df.format(dt.toDate()));
Here is the output:
lt=12:00:00.000
dtt=2014-07-08T12:00:00-0400
bdt=2014-07-08T18:01:30-0400
dt=2014-07-08T08:00:00-0400
As you can see, the dtt
and dt
should be the same time, but they are different by the local timezone offset.
Based on Matt Johnson's answer, I made a simple change in my code, replacing:
DateTime dt = lt.toDateTime(bdt.toInstant());
with
DateTime dt = new LocalDate(bdt).toDateTime(lt);
My code updated with the change (plus switching to Joda formatting) is as follows:
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ");
LocalTime lt = new LocalTime(12,0);
System.out.println(" lt="+lt);
DateTime dtt = lt.toDateTimeToday();
System.out.println("dtt="+dtt.toString(fmt));
DateTime bdt = new DateTime();
System.out.println("bdt="+bdt.toString(fmt));
DateTime dt = new LocalDate(bdt).toDateTime(lt);
System.out.println(" dt="+dt.toString(fmt));
Here's the new (correct!!) output.
lt=12:00:00.000
dtt=2014-07-09T12:00:00-0400
bdt=2014-07-09T00:15:35-0400
dt=2014-07-09T12:00:00-0400
Thanks Matt!
Consider:
LocalTime lt = new LocalTime(12, 0); // the scheduled time
LocalDate ld = new LocalDate(2014, 7, 8); // the day to run
DateTime dt = ld.ToDateTime(lt);
The above code will use the default time zone. If your event is scheduled to run in a particular time zone, use:
DateTimeZone tz = DateTimeZone.forID("America/New_York");
DateTime dt = ld.ToDateTime(lt, tz);