7

I am trying to convert Date with GMT +5:30 to EST with java 8 ZonedDateTime.

String inputDate = "2015/04/30 13:00";
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm", Locale.US);
LocalDateTime local = LocalDateTime.parse(inputDate, sourceFormatter);
// local : 2015-04-30T13:00
//Combining this local date-time with a time-zone to create a ZonedDateTime. 
ZonedDateTime zoned = local.atZone(TimeZone.getTimeZone("GMT+5:30").toZoneId());
// zoned : 2015-04-30T13:00+05:30[GMT+05:30]
ZonedDateTime zonedUS = zoned.withZoneSameInstant(TimeZone.getTimeZone("GMT-5:00").toZoneId());
// zonedUS : 2015-04-30T02:30-05:00[GMT-05:00]

I am expecting 3:30 AM EST but what I am getting is 2:30 AM EST as 1 PM IST= 3:30AM EST. What am I missing?

Gabriel Ilharco
  • 1,649
  • 1
  • 21
  • 34
Zeeshan
  • 11,851
  • 21
  • 73
  • 98
  • 2
    Um, that looks right to me. 13:00+05:30 = 07:30 UTC = 02:30-05:00. You've got a difference of 10:30 between +05:30 and -05:00, and 13:00-10:30 is 02:30... Why did you expect 03:30am? Note that Eastern Time is currently UTC-4, because it's EDT rather than EST... so the time in New York at that point would be 03:30 for example. – Jon Skeet Apr 30 '15 at 08:36
  • @JonSkeet when I googled `time EST` it showed me 3:30AM EST at 1:00 PM IST. It is because of daylight saving? – Zeeshan Apr 30 '15 at 08:39
  • 2
    Whatever you showed was being inaccurate if it *actually* claimed it was 3:30AM EST. It probably meant 3:30AM Eastern Time, not EST (and indeed that's what a Google search shows me)... EST is always UTC-5, whereas Eastern Time varies between EST (UTC-5) and EDT (UTC-4). If you want Eastern Time, you should use a zone ID of "America/New_York". (I would typically suggest using place-based zone IDs instead of offset ones in general...) – Jon Skeet Apr 30 '15 at 08:44
  • @JonSkeet. Thanks got the solution from your answer of this [question](http://stackoverflow.com/questions/10545960/how-to-tackle-daylight-savings-using-timezone-in-java) – Zeeshan Apr 30 '15 at 08:45
  • @JonSkeet. Can you please post your comment as an answer so that I can accept it? – Zeeshan Apr 30 '15 at 08:49
  • 3
    @Zeeshan Lesson learned: Avoid those 3-4 letter codes. Use [proper time zone names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Example: `America/New_York` or `America/Montreal`. – Basil Bourque Apr 30 '15 at 21:20

2 Answers2

11

It seems that whatever service you found was being over-helpful in interpreting what you meant and assumed North American Eastern Daylight Time (EDT) when you specified EST (Eastern Standard Time). Most, not all of the places using EST as standard time are using daylight saving time and hence were on EDT or offset UTC-04:00 on the date you use, April 30, 2015.

If it makes sense in your situation, you should always prefer to give time zone in the region/city format, as Asia/Kolkata and America/New_York. If you intended Eastern Time as in New York or Montréal, one may say that your “time zone” of GMT-5:00 was wrong and the cause of your unexpected result.

So your code becomes for example:

    String inputDate = "2015/04/30 13:00";
    DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm", Locale.US);
    LocalDateTime local = LocalDateTime.parse(inputDate, sourceFormatter);
    // local : 2015-04-30T13:00
    //Combining this local date-time with a time-zone to create a ZonedDateTime. 
    ZonedDateTime zoned = local.atZone(ZoneId.of("Asia/Kolkata"));
    // zoned : 2015-04-30T13:00+05:30[Asia/Kolkata]
    ZonedDateTime zonedUS = zoned.withZoneSameInstant(ZoneId.of("America/Montreal"));
    // zonedUS : 2015-04-30T03:30-04:00[America/Montreal]

I have made one other change: When using the modern classes from java.time, there is no point in also using the outdated TimeZone class, so I have taken that out. The code is slightly simpler, and more importantly, ZoneId.of(String) includes validation of your time zone string so you will discover any spelling error in the time zone name (like when I just happened to type a ( instead of the / in Asia/Kolkata — such happens all the time).

Most of the above has already been said in comments by Jon Skeet and others. I thought it deserved to go into an answer so it’s plain to see that the question has been answered.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

Though the question is old, felt like I could add more to the accepted answer.

A ZonedDateTime is different from an OffsetDateTime.

I would prefer to use ZonedDateTime when I'm getting a time for a specific location like "Asia/Kolkata", "Asia/Shanghai", "US/Pacific" (this time zone will change depending on the day of the year because of Daylight savings).

To illustrate with an example,

var pacific = ZonedDateTime.of(2020,11,01,1,59,0,0,ZoneId.of("US/Pacific"))
var afterAnHour = pacific.plusHours(1)

This will give me a time of

2020-November-01 01:59:00.000 AM -07:00[US/Pacific]

And if i add an hour to it, it will give me a time of

2020-November-01 01:59:00.000 AM -08:00[US/Pacific]

You can see that the hour component is same even after adding an hour to the time. This is because the daylight savings time has kicked in and the time zone is shifted from -07:00 to -08:00.

Now if i use an OffsetDateTime look what happens.

var offsetNow = OffsetDateTime.of(2020,11,01,1,59,0,0,ZoneOffset.of("-07:00"))
var offsetAfterAnHour = offsetNow.plusHours(1)

The offsetNow will be,

2020-November-01 01:59:00.000 -07:00

And adding an hour to it will be,

2020-November-01 02:59:00.000 -07:00

you can see that the hour component has become 2 after adding an hour.

The key point is a ZonedDateTime uses ZoneRules to calculate important properties like Daylight savings time so that it can adjust the time zone accordingly.

While the OffsetDateTime will not change the zone offset for anything.

Thirumalai Parthasarathi
  • 4,541
  • 1
  • 25
  • 43