Ranga Ron
Ranga Ron

Reputation: 163

The Calendar on Java doesn't working with "America/Santiago" DST timezone

I have a problem with Calendar object, it doesn't show correct offset on DST (Daily saving time) of America/Santiago timezone: My Example Code: TimeZone fromTimeZone = TimeZone.getTimeZone("America/Santiago");

    // Get a Calendar instance using the default time zone and locale.
    Calendar calendar = Calendar.getInstance();

    // Set the calendar’s time with the given date
    calendar.setTimeZone(fromTimeZone);

    calendar.set(Calendar.YEAR, 2015); // 2015
     calendar.set(Calendar.MONTH, 2); // Mar
     calendar.set(Calendar.DATE, 31); // 31

    calendar.set(Calendar.HOUR_OF_DAY, 7);
    calendar.set(Calendar.MINUTE, 45);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    System.out.println("offset: " + fromTimeZone.getOffset(calendar.getTimeInMillis())/(TimeUnit.MINUTES.toMillis(1)*60));

The output is: offset: -4 In the America/Santiago timezone at 3/31/2015, The offset should be -3. (ref: http://www.timeanddate.com/worldclock/converted.html?iso=20150331T00&p1=218&p2=232)

Why did the calendar get correct offset on this case? I had test with other timezone, It works fine on the DST time.

Thank you.

Upvotes: 4

Views: 2936

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 339332

The other Answers are correct about you needing to keep your tzdata up-to-date in your JVM.

java.time

Also, you are using date-time classes that are now obsolete, supplanted by the modern java.time classes defined in JSR 310.

ZoneId z = ZoneId.of( "America/Santiago" ) ;
LocalDate ld = LocalDate.of( 2015 , Month.MARCH , 31 ) ;
LocalTime lt = LocalTime.of( 7 , 45 , 0 , 0 ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

Adjust that moment into UTC. Same point on the timeline, different wall-clock time.

Instant instant = zdt.toInstant() ;

Get the rules for that time zone, a ZoneRules object.

ZoneRules rules = z.getRules() ;

Interrogate the rules. Get the offset-from-UTC in use at that moment, represented by ZoneOffset class.

ZoneOffset offset = rules.getOffset( instant ) ;

Ask if Daylight Saving Time (DST) was in effect at that moment in that zone. Notice the common misspelling used by the Java team in naming this method (“Saving” should be singular).

boolean isDst = rules.isDaylightSavings( instant ) ;

If in DST, get the amount of the DST adjustment as a Duration object. The Duration::toString method reports its value ( a number of hours, minutes, and seconds) in standard ISO 8601 format. For example, PT1H means 1 hour.

if( isDst ) {
    Duration d = getDaylightSavings​( instant ) ;
}

See this code run live at IdeOne.com.

zdt = 2015-03-31T07:45-03:00[America/Santiago]
instant = 2015-03-31T10:45:00Z
offset = -03:00
isDst = true
d = PT1H

Upvotes: 1

Lennart Regebro
Lennart Regebro

Reputation: 172309

Chile has usually switched from DST to STD in March, so your date would typically have been in standard time. However, since 2010, the changeover has been in April (except 2011 in May) and in 2015 Chile announced that it was going to stop changing and keep daylight savings permanently. (Edit: Chile has reversed its 2015 decision, and that year was the only one in which Chile did not fall back to standard time.)

Therefore I think that the problem most likely is that your zoneinfo database is very outdated. This can happen if you are running a copy of JVM that is not up to date, or if you are running a copy of JVM that takes it's zoneinfo data from the OS (This happens on some Linux distributions), and you haven't kept your OS up to date, or if you are running an OS which no longer receives updates.

In any case, the solution for Java is usually to update to the last JVM.

Upvotes: 2

Meno Hochschild
Meno Hochschild

Reputation: 44071

Without extra information about the underlying version of your timezone data it is hard to say what the reason exactly is. However, your last comment

The root cause is: The JDK on my system was 1.7 version so the Calendar didn't get correct time with this case. I tried with jdk 1.8 then get the expected output

tells me that you are obviously not interested in any analysis. So I update this answer for users who just want a solution without any need to know why the solution works.

If a user experiences problems with getting the correct timezone offset then the reason is usually using outdated data. Since the timezone data are built into the underlying JDK (if Java-8 or not does not really matter) you can do as first aid:

  1. Update your JVM to the newest version (also: the newest minor version, that is actually Java 8u45).

  2. If this does not help then use the newest version of TZUpdater-Tool in order to update the timezone data of your JVM - using prebuilt data.

  3. If this does still not help then you can - starting with version 2.0 of TZUpdater-Tool - use that tool to change your timezone data based on direct exploitation of the newest version of the original IANA/TZDB-Version (thanks to the information in the comment of Matt Johnson). Keep in mind that there is always a time gap between the release of the new TZDB-Version hosted on IANA and Oracle-Java-release-schedules.

  4. If you don't want to be dependent on Oracles release-planning or on the TZUpdater-tool then you can use an external library which has a built-in timezone-repository and gives you the opportunity to update it yourself as soon as possible (I know at least 2-3 such libraries but will not give any concrete recommendation here. It is easy to do appropriate research however).

Upvotes: 1

Related Questions