2

In the question A very strange date before 1970, I know the reason why two times looks only have difference of 1s, but sometimes we can get another value.

For example from that question:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000; 
    System.out.println(ld4-ld3);
}

The output will be 353 in a timezone of Shanghai, but will be 1 in other timezones.

My question is, how to calculate the difference without timezones? How to always get the correct difference?

Community
  • 1
  • 1
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • 4
    There is no "correct" difference. The difference depends on the timezone! – Jacob Jul 27 '11 at 09:09
  • If you want to use the same timezone all the time, have you tried creating a Calendar object and specifying the timezone you want to use? – Ricardo Jul 27 '11 at 09:15
  • Calendar standardCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); – Ricardo Jul 27 '11 at 09:17
  • 1
    @Ritchie: GMT may still have discontinuities. – Tom Anderson Jul 27 '11 at 09:25
  • 5
    The whole idea that the correct difference is 1 here is wrong. The correct difference is 353. Time is weird. Deal with it. – Tom Anderson Jul 27 '11 at 09:25
  • 353 is correct for people in Shanghai. If you treat the timestamp as GMT, the same thing will probably happen on some other date. You cannot "calculate the difference without timezones". – Thilo Jul 27 '11 at 09:27

3 Answers3

1

You can easily handle timezones with Joda Time.

  • You can create a DateTimeFormatter with the desired time zone and use it to parse the string. The DateTime instances can also be converted to other time zones.

  • You can ignore timezones completely by using the LocalDateTime class.

  • Also the Period class has methods like toStandardSeconds(), toStandardDuration(), normalizedStandard() etc. which "makes the assumption that all weeks are 7 days, all days are 24 hours, all hours are 60 minutes and all minutes are 60 seconds. This is not true when daylight savings time is considered, and may also not be true for some unusual chronologies. However, it is included as it is a useful operation for many applications and business rules."

Here is how to construct a timezoneless LocalDateTime either directly or by conversion from a timezoneful DateTime instance.

LocalDateTime a1 = new LocalDateTime(1927, 12, 31, 0, 0, 0, 0);
LocalDateTime a2 = new LocalDateTime(1928, 1, 2, 0, 0, 0, 0);
System.out.println(a1);
System.out.println(a2);
System.out.println(Seconds.secondsBetween(a1, a2).getSeconds()); // 172800 == 60 * 60 * 24 * 2 == 2 days without leap seconds

DateTime b1 = new DateTime(1927, 12, 31, 0, 0, 0, 0, DateTimeZone.forID("Asia/Shanghai"));
DateTime b2 = new DateTime(1928, 1, 2, 0, 0, 0, 0, DateTimeZone.forID("Asia/Shanghai"));
System.out.println(b1);
System.out.println(b2);
System.out.println(Seconds.secondsBetween(b1, b2).getSeconds());

LocalDateTime c1 = b1.toLocalDateTime();
LocalDateTime c2 = b2.toLocalDateTime();
System.out.println(c1);
System.out.println(c2);
System.out.println(Seconds.secondsBetween(c1, c2).getSeconds());

This will print as follows. Notice the funny timezone in Shanghai time before its timezone adjustment in 1927.

1927-12-31T00:00:00.000
1928-01-02T00:00:00.000
172800
1927-12-31T00:00:00.000+08:05:52
1928-01-02T00:00:00.000+08:00
173152
1927-12-31T00:00:00.000
1928-01-02T00:00:00.000
172800
Esko Luontola
  • 73,184
  • 17
  • 117
  • 128
  • -1 for saying it's possible, but giving no indication of how. – Tom Anderson Jul 27 '11 at 09:20
  • Yes, but what would that solve? This particular date will parse "better" in GMT, but there are other dates where GMT will also have leap seconds and stuff. – Thilo Jul 27 '11 at 09:20
  • The correct difference between two times takes leap seconds etc. into consideration, for the most common definition of "correct". – Esko Luontola Jul 27 '11 at 09:22
  • 1
    @Esko: So 353 is as "correct" as 1. The answer depends on the timezone. You cannot "calculate the difference without timezones." – Thilo Jul 27 '11 at 09:23
  • 1
    Thanks for the clarification. Downvote notionally removed for giving details, but a downvote notionally added for suggesting something which (a) doesn't fix the 'problem', as GMT may still have discontinuities, and (b) can be done equally well with classes in the JDK. – Tom Anderson Jul 27 '11 at 09:27
  • @Esko, could you please give me a runnable example with Joda-time? I tried, but not get it worked. – Freewind Jul 27 '11 at 09:52
  • There is now an example. Does that help? – Esko Luontola Jul 27 '11 at 10:10
1

In Shanghai, the timezone was changed from LMT to CST at this time.

Sunday, 1 January 1928, 00:00:00 clocks were turned backward 0:05:52 hours to Saturday, 31 December 1927, 23:54:08 local standard time instead

http://www.timeanddate.com/worldclock/clockchange.html?n=237&year=1927

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Did something similar happen with GMT as well? – Thilo Jul 27 '11 at 09:30
  • AFAIK, GMT hasn't changed since 1675. UTC is a much more recent variation on this. http://en.wikipedia.org/wiki/Time_zone – Peter Lawrey Jul 27 '11 at 09:36
  • But haven't there been leap seconds? That's not five minutes, though. http://en.wikipedia.org/wiki/Leap_second – Thilo Jul 27 '11 at 09:51
  • I believe that is one of the differences between UTC and GMT. Java uses GMT which doesn't have leap seconds. Every day is exactly 24*60*60*1000 milli-seconds long. – Peter Lawrey Jul 27 '11 at 10:07
-1

Instead of converting each date in long put the code :

long i = (sDt4.getTime() - sDt3.getTime()) / (1000);
System.out.println(i);

Output is:

1
Rajshri
  • 4,163
  • 2
  • 15
  • 17