jack
jack

Reputation: 1942

java gregoriancalendar off by an hour

I did:

GregorianCalendar gc = new GregorianCalendar(Locale.French);

And the hour is off by one hour. I get 14:17 instead of 15:17. My first thought was DST, but I think gregoriancalendar takes that into account.

The time is set correctly on my pc.

Upvotes: 4

Views: 759

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338634

tl;dr

As noted in a comment, you confused using a Locale object with specifying a time zone. A locale has nothing to do with a time zone, and a locale does not affect the meaning of the date-time value. A locale affects only the formatting of a String used in presentation of the date-time value.

No locale needed when capturing the current moment. But we do need a time zone.

Instant.now().atZone( ZoneId.of( "America/Montreal" ) )

…or shorter version…

ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )

java.time

You are using troublesome old legacy date-time classes, now supplanted by the java.time classes.

Work in UTC

Much of your business logic, data storage, and data exchange should be in UTC. Think of UTC as “the One True Time”.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.now();

Specify time zone

As you figured out, you should always specify the desired/expected time zone. For any given moment, the date and the time-of-day vary around the world by zone.

Specify a proper time zone name in the format of continent/region. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

Specify locale

Be aware that time zone and locale are orthogonal, completely separate issues.

  • Time zone determines the meaning of the date-time, how we view its wall-clock time.
  • Locale determines (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.

This means we can mix-and-match any time zone with any locale. We can have a date-time in zone Europe/Paris with a locale of Locale.KOREA. Or a zone of Pacific/Auckland with Locale.CANADA_FRENCH.

So locale only impact presentation of the date-time, how we generate a String representation of the date-time.

You can specify a custom formatting pattern for generation of strings. But better to let java.time automatically localize.

Locale l = Locale.CANADA_FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                       .withLocale( l );
String output = zdt.format( f );

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 1

Ralph
Ralph

Reputation: 120791

I am not sure what you are trying, but GregorianCalendar(Locale) is always based on your default time zone. -- Maybe you should have a look at GregorianCalendar(TimeZone zone, Locale aLocale)

Upvotes: 0

bert
bert

Reputation: 7696

The constructor you use is creating a Calendar with the default Timezone (javadoc), this might not be the timezone correct fpr the given locale. At leasst, thats how i read the javadoc. Try using a different constructor and pass your TZ in.

Upvotes: 2

Related Questions