Java GregorianCalendar

时间:2012-08-29 01:51:48

标签: java timezone

我正在尝试理解GregorianCalendar学习java作为经验丰富的Delphi(pascal)开发人员。根据文档,1970年1月1日0:00:00是计算从这一点开始经过的时间的参考。所以,在实验中,我设置了一个新变量

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

然后我读了时间

cal2.getTimeInMillis()

根据定义,这应该等于零。但我得到了18,000,000毫秒。这是5个小时。我在想这与时区有关?有任何建议,我在东区。

如果是这样,我该如何解释?我真的想了解所以我可以计算两次之间的秒数差异。不理解这一点,我无法继续! 谢谢! 道格

4 个答案:

答案 0 :(得分: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));
  }
}

产生这个:

Eastern Standard Time: 18000000 (offset -18000000)
Coordinated Universal Time: 0 (offset 0)

答案 1 :(得分:1)

我知道这不会直接回答您的问题,但GregorianCalendar可能不是最好的方法。我建议您使用像Joda Time这样的库,因为您专门寻找DurationPeriod等概念。另请查看ThreeTen JSR 310的RI Java 8,计划用于{{3}}。

这是一个 JodaTime 解决方案,用于计算经过的时间(以秒为单位)。

  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();

答案 2 :(得分:0)

我打赌这是东部时区。最大的问题是:你必须考虑到它吗?你打算在同一时区计算/记录时间吗?这个类中有很多功能,它们非常臃肿,但非常方便。

GregorianCalendar类确实包含时区功能,也可以为您提供DST偏移。

答案 3 :(得分:0)

北美东海岸与UTC

您的GregorianCalendar带有时区。但是epoch的定义是UTC。 1970年的第一个时刻,在北美东海岸的比起1970年的第一个世界时间晚了五个小时。所以你要比较苹果和橘子。

让我们再看看,但使用现代的 java.time 类。

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

相比之下,猜测你的时区是America/New_York,1970年的第一个时刻在该地区晚上 5小时(18,000,000毫秒)比第一时刻 1970年的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 = 5小时* 60分钟/小时* 60秒/分钟* 1,000毫秒/秒

java.time

GregorianCalendar课程是一个有缺陷,设计糟糕,麻烦的课程。躲开它。它现在由java.time.ZonedDateTime取代。

Instant

Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instant = Instant.now() ;
  

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

ZonedDateTime

您可以从UTC调整到特定时区。你最终会得到同一时刻,即时间轴上的相同点,但是不同的挂钟时间。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4个字母伪区域,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。没有“东部时间”之类的东西,请使用America/New_York等时区。

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

申请Instant以获得ZonedDateTime

ZonedDateTime zdt = instant.atZone( z ) ;
  

zdt.toString():2018-02-06T03:59:56.156787 + 01:00 [非洲/突尼斯]

从纪元算起

将日期时间值作为纪元参考日期的计数处理是不明智的。这样的整数对于人眼来说不可能作为日期时间读取,因此难以或不可能调试和发现无效值。

但是如果你坚持,你可以从1970年的第一个时刻,1970-01-01T00:00Z中提取毫秒数。

小心数据丢失。在以毫秒为单位生成此计数时,Instant中的任何微秒或纳秒都将被忽略。

long millisSinceEpoch = instant.toEpochMilli() ;
  

1517885996156

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore