0

I set my Calendar instance to a UTC date at 00:00 however once i return the result its 1 hour ahead

Calendar cal = Calendar.getInstance(TIMEZONE_UTC, Locale.ENGLISH);
cal.set(2017, 12 - 1, 15);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
System.out.println(cal.getTime());
// Fri Dec 15 01:00:00 CET 2017 but should be 00:00:00

I suppose there is the winter/summer offset but I didn't found any description in the Gregorian or Calendar Element to handle this issue

Maevy
  • 261
  • 4
  • 24
  • 1
    You are getting the correct time, 00:00:00 UTC. What is fooling you is that `Date.toString()` (implicitly called from `System.out.println()`) is converting the time to your own time zone (using the JVM time zone setting) for the string generated. – Ole V.V. Dec 21 '17 at 09:54
  • 1
    I recommend you stop using the long outdated `Calendar` class. [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/), is so much nicer to work with. And using a `ZonedDateTime` (or `OffsetDateTime` or `Instant`) from the modern API will solve your issue. – Ole V.V. Dec 21 '17 at 10:28
  • Are you expecting midnight on this date in UTC to also be midnight (00:00:00) in the CET time zone simultaneously? Not possible, as **CET is an hour ahead of UTC on that date** for that particular unidentified zone. I say unidentified because CET is not a time zone but the effect of a time zone such as `Europe/London`. – Basil Bourque Dec 21 '17 at 11:04
  • 1
    In fewer words: 00:00:00 UTC on that date ***is*** 01:00:00 CET. – Basil Bourque Dec 21 '17 at 11:14

2 Answers2

4

I am getting the impression that you are really after just the date of December 15, 2017, and just wanted to make sure that there is no unexpected hour-of-day? If so, LocalDate from java.time, the modern Java date and time API, is made for you:

LocalDate ld = LocalDate.of(2017, Month.DECEMBER, 15);
System.out.println(ld);

This prints

2017-12-15

No hours, minutes or seconds to be concerned about.

If you do need a date-time at 00:00 UTC (the time I used to call midnight until Basil Bourque’s comment), there are several ways to obtain it. One of them is:

    OffsetDateTime utcDateTime = LocalDateTime.of(2017, Month.DECEMBER, 15, 0, 0)
            .atOffset(ZoneOffset.UTC);
    System.out.println(utcDateTime);

This prints

2017-12-15T00:00Z

The Z in the end means UTC or offset zero. You see that the time of day is 00:00 as you wanted.

The Calendar class that you used in the question is long outdated, so I recommend you don’t use it anymore. java.time, the modern Java date and time API also known as JSR-310, is so much nicer to work with.

What went wrong in your code?

While a Calendar does contain a time zone (you initialized it to TIMEZONE_UTC), a Date (another outdated class) doesn’t. So when you convert to Date using cal.getTime() you lose the information that you wanted the time to be in UTC. Next (and this confuses many), when you print the date, you implicitly call Date.toString(), and this method grabs your JVM’s time zone setting and produces a string with the time in this time zone. So apparently you are (like I am) in a time zone that is at UTC+01:00 in December. The following two date-times denote the same point on the timeline:

Fri Dec 15 01:00:00 CET 2017
Fri Dec 15 00:00:00 UTC 2017
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 2
    Good Answer, but I suggest using the phrase "first moment of the day" rather than "midnight". The "midnight" term is amorphous, meaning different things to different people in different contexts. Note that the Joda-Time project made a major breakthrough in dropping the concept(s) and the term, and deprecating several classes, instead going with a "start of day" concept in both the terminology and the classes. – Basil Bourque Dec 21 '17 at 11:10
  • Thx, @BasilBourque, edited. – Ole V.V. Dec 21 '17 at 13:10
1

The reason why you see local time printed is you're displaying it via an instance of Calendar using Date.toString() which uses the local timezone(implicitly use the system timezone).

rimonmostafiz
  • 1,341
  • 1
  • 15
  • 33
  • This is incorrect, different semantics than the Question. The Question sets the `Calendar` object to 00:00:00 in UTC, then in calling `Calendar::getTime` instantiates a `Date` that carries no applicable time zone (always in UTC) but whose `Date::toString` dynamically applies the JVM’s current default time zone which must one of the zones an hour ahead of UTC. In contrast, this Answer sets the `Calendar` object to 00:00:00 in BST (London time), **an entirely different moment**, an hour earlier than the moment in the Question. – Basil Bourque Dec 21 '17 at 11:22