8

I am having a hard time comparing two DateTime objects that are in different TimeZones.

What I already know:

1) I know that the "isBefore()" method does not take TimeZones into account. So, the "if" condition bellow is not true (even though I would like it to be true):

long aRandomTimeSinceTheEpoch = 1234567789L;

String TIMEZONE_SYDNEY_AUSTRALIA = "Australia/Sydney";
DateTimeZone sydneyTimeZone = DateTimeZone.forID(TIMEZONE_SYDNEY_AUSTRALIA);
Chronology chronologySydney = GJChronology.getInstance(sydneyTimeZone);

String TIMEZONE_NEWYORK = "America/New_York";
DateTimeZone newYorkTimeZone = DateTimeZone.forID(TIMEZONE_NEWYORK);
Chronology chronologyNewYork = GJChronology.getInstance(newYorkTimeZone);

DateTime sydneyDateTime = new DateTime(aRandomTimeSinceTheEpoch, chronologySydney);
DateTime newYorkDateTime = new DateTime(aRandomTimeSinceTheEpoch, chronologyNewYork);

if( newYorkDateTime.isBefore(sydneyDateTime) ){
    System.out.println("true");
}

2) Based on this answer (https://stackoverflow.com/a/8793980) it seems the correct way to do it is by Period instead, as Period is the right concept for what I am trying to do. However, that code throws an "UnsupportedOperationException - if the period contains years or months" exception sometimes (because I am dealing with dates that can be up to 2 years away from each other).

In short, all I want is an "isBefore()" method that takes TimeZones into account. (and that does not throw exceptions like the one above). How can I achieve this in Joda?

Community
  • 1
  • 1

2 Answers2

10

What you're missing is that anytime you are measuring in seconds or milliseconds from the epoch - that is always in UTC.

So your sydneyDateTime and newYorkDateTime may have different zones, but since they are both originating from the same aRandomTimeSinceTheEpoch value, then they both occur at the same exact moment. Thus neither is before the other.

By analogy, it's like asking which is greater, 1 inch or 2.54 centimeters?

From your comments, it looks like you would like to compare the local times in each time zone, which you can do like this:

if( newYorkDateTime.toLocalDateTime().isBefore(sydneyDateTime.toLocalDateTime()) )

Note that if you are always starting from the same source instant, then this value will always be true. Just like 2.54 is always greater than 1.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thank you for replying Matt. I am aware of that. The code I put was just an example to make my question clearer. But my question is how I would compare the two dates with the TimeZone info? I know they all represent the same instant in time from the epoch (that is why isBefore fails to do what I want as, internally, isBefore uses the milliseconds from the epoch to compare the DateTime objects), but how should I do it then if I DO NOT want to ignore the TimeZones? – Bitcoin Cash - ADA enthusiast Aug 18 '13 at 23:28
  • Just to clarify, do you mean you wish to compare the *local* time in Sydney against the *local* time in New York? (Like saying 2.54 is greater than 1 in my analogy) – Matt Johnson-Pint Aug 18 '13 at 23:30
  • Correct. The Period solution from the second point of my question gets pretty close except that it fails when the two DateTime being compared are too far away from each other (ie, when they differ from each other by more than 1 month). – Bitcoin Cash - ADA enthusiast Aug 18 '13 at 23:33
  • See my updated answer using `.toLocalDateTime()`. You shouldn't have to concern yourself with `Period` math just for comparisons. – Matt Johnson-Pint Aug 18 '13 at 23:43
  • This seems to be it! I will test later today and accept your answer if it works well. Can't believe it is that simple. :) – Bitcoin Cash - ADA enthusiast Aug 18 '13 at 23:59
2

use getMillis() on each date to obtain the milliseconds and compare those, that will give you an absolute pair of numbers against which to compare.

  • 1
    Thank you for replying, but I believe you did not understand my question. The getMillis() gives me the exact same value, no matter on which TimeZone I am in. So, I cannot use it to compare. – Bitcoin Cash - ADA enthusiast Aug 18 '13 at 23:24
  • If `getMillis()` gives you the exact same value then your times are the exact same instant. As Matt has mentioned it appears that what you want is to compare the numeric values of the years/months/days/hours/mins/secs of the two times, in which case turning them in to `LocalDateTime` is one way to do it. It *might* be a bit faster to convert one date to the other's timezone using `withZoneRetainFields()` and then compare them, but I haven't tested it. –  Aug 19 '13 at 17:38