My problem is pretty straigtforward explained :
if I do this :
public class Main {
public static void main(String[] args) throws Exception {
Date d = new Date(0L );
System.out.println(d);
}
}
I get the following output : Thu Jan 01 01:00:00 CET 1970
According to the doc, I was expecting : Thu Jan 01 00:00:00 CET 1970
I would like was going wrong...
EDIT :
Indeed, I read the doc too fast. I should have Thu Jan 01 00:00:00 GMT 1970
So, how can I force the use of GMT, and ignore all local time ?
Edit, Solution :
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("H:m:s:S");
SimpleTimeZone tz = new SimpleTimeZone(0,"ID");
sdf.setTimeZone(tz) ;
Date d = new Date(0L );
System.out.println( sdf.format(d));
}
The Epoch is defined as 00:00:00 on 1970-1-1 UTC. Since CET is UTC+1, it's equal to 1AM your time.
If you look at the Date(long) constructor, you'll see that it expects the value to be the number of milliseconds since the epoch, UTC:
Allocates a Date object and
initializes it to represent the
specified number of milliseconds since
the standard base time known as "the
epoch", namely January 1, 1970,
00:00:00 GMT.
Regarding your desire to force GMT instead of your local time zone: In short, the Date instance always uses GMT. If you just want to format the output String so that it uses GMT have a the DateFormat class, and specifically, its setTimeZone() method.
This might be related to your locale settings. Assuming you're French and not French-Canadian, it would seem as if your timestamp is being treated as timestamp without timezone, and the Date
constructor attempts to correct for this, adding an hour to the date.
If this is undocumented behavior or not, I cannot tell you.
Edit: Read error: CET != UTC :/
So yeah, Locale time zone.
Reedit: For utter and absolute clarity.
Output: Thu Jan 01 01:00:00 CET 1970
Your expected output: Thu Jan 01 00:00:00 CET 1970
Actual expected output: Thu Jan 01 00:00:00 GMT 1970 ( ≡ Thu Jan 01 01:00:00 CET 1970)
tl:dr
Instant.EPOCH
.toString()
1970-01-01T00:00:00Z
Date::toString
lies
You've learned one of the many reasons to avoid using the java.util.Date/Calendar classes: a Date
instance has no time zone information, yet it's toString
method uses your default time zone when rendering a string for display. Confusing because it implies the Date has a time zone when in fact it does not.
Avoid Date
/Calendar
Instead of Date/Calendar, you should be using Joda-Time or the new Java 8 classes, java.time.* from JSR 310.
java.time
Use the Instant
class as the equivalent of Date
, a moment on the timeline in UTC.
Instant.now()
For the epoch reference date, use the constant.
Instant.EPOCH.toString()
1970-01-01T00:00:00Z
If by "ignore all time" you mean that you really want a date-only value without time-of-day, use the LocalDate
class.
LocalDate.ofEpochDay( 0L )
1970-01-01
Joda-Time Example
Update: The Joda-Time project is now in maintenance mode with the team advising migration to the java.time classes.
In Joda-Time, a DateTime instance does indeed know its own time zone. You can use a formatter to create string outputs in other time zones, if desired.
Here's your code aiming at the Unix time Epoch, but using Joda-Time 2.3.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
DateTimeZone timeZone_Paris = DateTimeZone.forID( "Europe/Paris" );
DateTime epochParis = new DateTime( 0L, timeZone_Paris );
DateTime epochUtc = new DateTime( 0L, DateTimeZone.UTC );
Dump to console…
System.out.println( "epochParis: " + epochParis );
System.out.println( "epochUtc: " + epochUtc );
When run…
epochParis: 1970-01-01T01:00:00.000+01:00
epochUtc: 1970-01-01T00:00:00.000Z
Convert To UTC/GMT
So, how can i force the use of GMT, and ignore all local time ?
To use UTC/GMT (no time zone offset), either:
- Convert a DateTime to another instance with a different time zone
(Joda-Time makes things immutable for thread-safety, so we don't actually convert, we create new instances based on old ones.)
- Use a formatter to create strings displayed for a specified time zone.
// To use UTC/GMT instead of local time zone, create new instance of DateTime.
DateTime nowInParis = new DateTime( timeZone_Paris );
DateTime nowInUtcGmt = nowInParis.toDateTime( DateTimeZone.UTC );
Dump to console…
System.out.println( "nowInParis: " + nowInParis );
System.out.println( "nowInUtcGmt: " + nowInUtcGmt );
When run…
nowInParis: 2013-12-22T08:40:01.443+01:00
nowInUtcGmt: 2013-12-22T07:40:01.443Z
CET is one hour ahead of GMT, which is the time zone used to define the Epoch.