3

I'm trying to understand GregorianCalendar learning java as a seasoned Delphi (pascal) developer. According to the documentation, January 1, 1970 at 0:00:00 is the reference for calculating time elapsed in seconds from this point. So, in experimenting, I set a new variable

GregorianCalendar cal2 = new GregorianCalendar(1970, 0, 1, 0, 0, 0); //January=0, Day=1, Hour=0, Min=0, Sec=0

then I read the time

cal2.getTimeInMillis()

This should equal zero by definition. Yet I get 18,000,000 milliseconds. This is 5 hours. I am thinking this has to do with the time zone? Any suggestions, I am on Eastern Zone.

If so, how do I account for this? I am really trying to understand so I can calculate differences in seconds between two times. Without understanding this, I can't proceed! Thanks! Doug

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • "*calculating time elapsed in seconds*" actually, its the time elapsed in milliseconds – MadProgrammer Aug 29 '12 at 01:53
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/9/docs/api/java/util/Date.html), [`java.util.GregorianCalendar`](https://docs.oracle.com/javase/9/docs/api/java/util/GregorianCalendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes built into Java 8 & Java 9. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Feb 06 '18 at 03:24

4 Answers4

2
package so;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class BeginningOfTime {

  public static void main (final String[] args) {

    final Calendar localTZ = new GregorianCalendar (1970, 0, 1, 0, 0, 0);
    dump (localTZ);

    final Calendar utcTZ = new GregorianCalendar ();
    utcTZ.clear ();
    utcTZ.setTimeZone (TimeZone.getTimeZone ("UTC"));
    dump (utcTZ);
  }

  private static final void dump (final Calendar c) {

    System.out.printf ("%s: %d (offset %d)%n",
                       c.getTimeZone ().getDisplayName (),
                       c.getTimeInMillis (),
                       c.get (Calendar.ZONE_OFFSET));
  }
}

Yields this:

Eastern Standard Time: 18000000 (offset -18000000)
Coordinated Universal Time: 0 (offset 0)
carej
  • 596
  • 1
  • 6
  • 18
1

I know that this don't directly answers your question, but GregorianCalendar may not be the best approach here. I would recommend you to use a library like Joda Time since your are specifically looking for concepts such as Duration and Period. Also take a look at ThreeTen the RI of JSR 310, which is planned for Java 8.

Here is a JodaTime solution to calculate time elapsed in seconds.

  DateTime start = new DateTime(2012, 3, 25, 0, 0, 0, 0);
  DateTime end = new DateTime(2012, 3, 26, 0, 0, 0, 0); 
  int seconds = Seconds.secondsBetween(start, end).getSeconds();
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
0

I bet it is the Eastern Time Zone. The big question is: do you have to account for it? Are you going to calculate/record time in the same timezone? There's a lot of functionality into that class to where it gets to be very bloated, yet very handy.

The GregorianCalendar class does include time zone functionality and can also do things like give you the DST offset.

Joe Plante
  • 19
  • 2
0

East coast of North America versus UTC

Your GregorianCalendar carries a time zone. But the definition of your epoch is UTC. The first moment of 1970 on east coast of North America comes five hours later than the first moment of 1970 in UTC. So you are comparing apples to oranges.

Let's take another look, but use the modern java.time classes.

Instant instantEpochConstant = Instant.EPOCH ;  // Expect 1970-01-01T00:00:00Z.

instantEpochConstant.toString(): 1970-01-01T00:00:00Z

Instant instantZeroMillis = Instant.ofEpochMilli( 0L ) ;  // Expect 1970-01-01T00:00:00Z.

instantZeroMillis.toString(): 1970-01-01T00:00:00Z

long millisSinceEpoch = Instant.parse( "1970-01-01T00:00:00Z" ).toEpochMilli() ; // Expect zero.

millisSinceEpoch.toString(): 0

In contrast, guessing your time zone is America/New_York, the first moment of 1970 in that region comes 5 hours (18,000,000 milliseconds) later than first moment of 1970 in UTC.

ZonedDateTime zdt = ZonedDateTime.of(
        LocalDate.of( 1970 , Month.JANUARY , 1 ) ,
        LocalTime.MIN ,
        ZoneId.of( "America/New_York" )
);
Instant instantFromNewYork = zdt.toInstant() ;
long epochMillisNewYork = instantFromNewYork.toEpochMilli() ;

zdt.toString(): 1970-01-01T00:00-05:00[America/New_York]

instantFromNewYork.toString(): 1970-01-01T05:00:00Z

epochMillisNewYork: 18000000

5 * 60 * 60 * 1000 = 18,000,000 = five hours * 60 minutes/hour * 60 seconds/minute * 1,000 milliseconds/second

java.time

The GregorianCalendar class is a flawed, poorly-designed, troublesome class. Avoid it. It is now replaced by java.time.ZonedDateTime.

Instant

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now() ;

instant.toString(): 2018-02-06T02:59:56.156787Z

ZonedDateTime

You can adjust from UTC into a particular time zone. You will end up with the same moment, the same point on the timeline, but a different wall-clock time.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!). No such thing as "Eastern time", use a time zone such as America/New_York.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;

Apply to the Instant to get a ZonedDateTime.

ZonedDateTime zdt = instant.atZone( z ) ;

zdt.toString(): 2018-02-06T03:59:56.156787+01:00[Africa/Tunis]

Count from epoch

Handling your date-time values as a count from epoch reference date is ill-advised. Such integer numbers are impossible for human eyes to read as date-times, so debugging and spotting invalid values is difficult or impossible.

But if you insist, you can extract a count of milliseconds from the epoch of first moment of 1970 in UTC, 1970-01-01T00:00Z.

Beware of data loss. Any microseconds or nanoseconds in your Instant are ignored while generating this count in milliseconds.

long millisSinceEpoch = instant.toEpochMilli() ;

1517885996156


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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154