Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Joda Time subtracting 24 hours from an instance of MutableDateTime, I would like to know why

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

like image 236
kg. Avatar asked Oct 28 '10 17:10

kg.


1 Answers

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.)

like image 89
Affe Avatar answered Oct 07 '22 02:10

Affe