-1

System Time should be set Hong Kong (UTC+08:00)

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class HKtimeZone {
    public static void main(String [] args ) throws ParseException{

        String dateString = "1900-01-01 08:00:00.000";
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date endDate = df.parse(dateString);

        System.out.println(endDate);
    }
}

Above piece of code prints:

Mon Jan 01 08:05:43 CST 1900

instead of

Mon Jan 01 08:00:00 CST 1900.

I know the reason/history of it but I want to know is there any know solution to it in Java. I have problem in my project specific to this time so I am not asking it just for fun or testing someone knowledge.

Note : Setting timezone to UTC/GMT make situation more worse.

vineeshchauhan
  • 765
  • 2
  • 7
  • 14
  • 1
    What's your java version? And what's the output of `System.out.println(TimeZone.getDefault());`? - If you use java 8, also check the ouput of `System.out.println(ZoneId.systemDefault());` –  May 26 '17 at 12:17
  • Just set the timezone on your parser, don't rely on the system timezone. Add `df.setTimeZone(TimeZone.getTimeZone("CST"));` – pvg May 26 '17 at 12:22
  • 3
    @pvg The problem is that **CST** can be *China Standard Time* or *Central Standard Time*. But the situation described above occurs only in the first case (China), and `TimeZone.getTimeZone("CST")` creates the second one (in which the situation above doesn't happen). That's the problem with these 3-letter timezone names, they're ambiguous and [not standard](https://stackoverflow.com/a/18407231/7605325). –  May 26 '17 at 13:16
  • 1
    @Hugo ah of course, doh. But I'd still make the same suggestion - set the timezones on your parsers and formatters explicitly if you care about precise control. The diversion though system timezone seems to make the whole thing more complicated than necessary. – pvg May 26 '17 at 13:29
  • Setting only in the parser causes a different output. For me, when using *Asia/Shanghai*, it gives **Sun Dec 31 20:53:32 BRT 1899** (it converts to my default timezone, which is *BRT* (aka *America/Sao_Paulo*). But I agree that setting the default timezone can cause side-effects in other parts of the application and it's better to set it only where you need it (whenever it's possible). –  May 26 '17 at 13:34
  • 1
    @Hugo Both parser and formatter. Part of the problem in this question is that it basically just does Date.toString() which doesn't even offer any guarantees it will actually print a timezone in the first place. If you instantiate a second `SimpleDateFormatter`, set the tz on it, use a format with a 'z' at the end it will reliably format for that tz whether you're in São Paulo or Shanghai. – pvg May 26 '17 at 16:18
  • The problem is not due to any ambiguity in name of time zones. Timezone will be decided on the fly depending upon from where the user is accessing my application. If they are in Beijing/Hong Kong, It will UTC+08:00, if they are in US it will be UTC-05:00. Timezone will be what they set on their local machines. – vineeshchauhan May 27 '17 at 06:08
  • I can't set the timezone in parser on the fly. It will always be timezone of machine used to access my app. – vineeshchauhan May 27 '17 at 06:08

2 Answers2

1

According to my Java 8, Shanghai was at UTC+08:05:43 at that time in history, while Hong Kong was at UTC+07:36:42. I am not sure what your exact problem is, but I think one of these solutions should work:

  1. Give an explicit time zone to everything you do with times.
  2. Use LocalDateTime. This is a date and time without any time zone specification, so this will make sure that 8:00 stays 8:00.

Demo code:

    String dateString = "1900-01-01 08:00:00.000";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    LocalDateTime dateTime = LocalDateTime.parse(dateString, dtf);
    System.out.println(dateTime);

    ZonedDateTime shanghaiDateTime = dateTime.atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(shanghaiDateTime);

    ZonedDateTime hongKongDateTime = dateTime.atZone(ZoneId.of("Asia/Hong_Kong"));
    System.out.println(hongKongDateTime);

    OffsetDateTime utcPlus8DateTime = dateTime.atOffset(ZoneOffset.ofHours(8));
    System.out.println(utcPlus8DateTime);

Output:

1900-01-01T08:00
1900-01-01T08:00+08:05:43[Asia/Shanghai]
1900-01-01T08:00+07:36:42[Asia/Hong_Kong]
1900-01-01T08:00+08:00
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    I will give it a try and let you know. – vineeshchauhan May 27 '17 at 06:10
  • I tried it. Problem is that as soon I convert ZonedDateTime to date, issue reappear. I have some legacy code which requires date object only and I have to convert the result to date. Date out=Date.from(dateTime.atZone(ZoneId.systemDefault()) .toInstant()); System.out.println(out); Mon Jan 01 07:54:17 CST 1900 – vineeshchauhan May 29 '17 at 06:11
0

I could reproduce your problem setting my default timezone to Asia/Shanghai:

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

This gives me the same output you're getting:

Mon Jan 01 08:05:43 CST 1900

This happens because that's the timezone rules for the year 1900 in Shanghai.
If you go to this page and choose "Time zone changes for 1900 - 1924", you'll see that in 1900 the date and time are "UTC +8:05:43 hours all of the period".

So Java is just showing the time configured for that timezone, at that year.


But you mentioned that "System Time should be set Hong Kong (UTC+08:00)"

So if you change your default timezone to Hong Kong, it works:

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Hong_Kong"));
String dateString = "1900-01-01 08:00:00.000";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date endDate = df.parse(dateString);
System.out.println(endDate);

The output is:

Mon Jan 01 08:00:00 HKT 1900

Note that the timezone changed from CST (China Standard Time, the "3-letter equivalent" to Asia/Shanghai) to HKT (the 3-letter name for Hong Kong's timezone).

  • When I say "System Time should be set Hong Kong (UTC+08:00)" it means you need to change the timezone of your machine to Hong Kong(UTC+08:00) i.e. physical machine. I can't set the timezone on the fly in my code as our application is accessed across the globe. – vineeshchauhan May 27 '17 at 06:01