tags:

views:

68

answers:

2

I do not understand why MutableDateTime.setDate() is setting the time to "yesterday" (see the log timestamp hours - it is 20:28). Is this timezone related? Do I need to set something on the formatter?

I would expect that after calling setDate with "10/27/2010", the date would be the same as the parsed date 00:00 EDT 10/27/10, instead of 20:28 EDT 10/26/10. This is 24 hours ago from "now".

What am I missing here, or how should I edit the code to get the desired result? I am new to Joda Time, and would like to solve this mystery.

DateTimeFormatter dateFormatterJ = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTimeFormatter timestampFormatJ = DateTimeFormat.forPattern("HH:mm zzz MM/dd/yy");

MutableDateTime startDate = new MutableDateTime();

log.info("parsed date " + 
    timestampFormatJ.print(dateFormatterJ.parseMutableDateTime(startDateString)));

startDate.setDate((dateFormatterJ.parseMutableDateTime(startDateString)));

log.info("startDate: " + timestampFormatJ.print(startDate));

In this case, startDateString is simply "10/27/2010".

here is the log output:

10-27 20:28:55 INFO parsed date: 00:00 EDT 10/27/10
10-27 20:28:55 INFO startDate: 20:28 EDT 10/26/10

Thanks

+4  A: 

The simple answer would be, because the javadoc says so.

public void setDate(ReadableInstant instant)

Set the date from another instant. The time part of this object will be unaffected.

Parameters: instant - an instant to copy the date from, time part ignored

Throws: IllegalArgumentException - if the object is invalidobject is invalid

When Joda says 'Date' it means the human meaning of the word Date. "The year-month-day portion of this value", not the logical equivalent of a java.util.Date. (the whole point of joda being to introduce some natural, sensible, semantics to handling date and time.)

EDIT: To answer your 'how to fix' question, simply do:

MutableDateTime startDate = new MutableDateTime(dateFormatterJ.parseMutableDateTime(startDateString));

Or else manually zero out the time portions of course.

EDIT 2: Hmm, I apparently did not read carefully enough, this is only half of the answer. Will check.

EDIT 3: well this bugged me so much that I took a minute to look for it.

public void setDate(final ReadableInstant instant) {
    long instantMillis = DateTimeUtils.getInstantMillis(instant);
    Chronology instantChrono = DateTimeUtils.getInstantChronology(instant);
    DateTimeZone zone = instantChrono.getZone();
    if (zone != null) {
        instantMillis = zone.getMillisKeepLocal(**DateTimeZone.UTC**, instantMillis);
    }
    setDate(instantMillis);
}

For some reason, it's rolling your absolute time forward into UTC before setting the date. So you give it 10/27/2010 00:00 EDT and it sets the absolute magnitude of time to the number of milliseconds that represent 10/27/2010 00:00 UTC, which of course is only 6 or 7 PM the day before. Then it finds the EDT date value of that to be 10/26.

Couldn't say if that's somehow intended or if it's a bug that's been there for 2 years or what.)

Affe
Thank you, Affe. Your fix of newing up the MutableDateTime with the parsed date string instead of using setDate() worked. The explanation into the root cause is also much appreciated. I would interpret this as a bug, but there may be differing opinions.
kg
kg
+1  A: 

When parsing a string that does not contain a GMT offset or time-zone ID, you must do one of three things:

  • do nothing, and accept that the string is parsed in the default time zone
  • specify the time zone to parse in using withZone() on the formatter
  • use parseLocalDate() instead of parseMutableDateTime()

The last is the preferred solution, as it correctly parses the data that was actually input, which was a date without time, offset or zone.

Using parseLocalDate() in the test code correctly parses the date.

JodaStephen
a google for +"parseLocalDate" +joda returns a single google groups post from June and some code in GWT. I did try it using withZone() before looking at the source and the result is the same. It seems like even though I specify a zone, the code in MutableDateTime sees it on my Chronology, then goes and shifts it into UTC instead of shifting it into the timezone of the MutableDateTime.
Affe