在Java中创建时间戳的正确方法是什么?

3

如果给定了年、月、日、小时、分钟和秒,创建Java UTC (GMT)时间戳的正确方法是什么?

我考虑过的选项,但还没有被说服的:

1-使用已弃用的Date构造函数

java.util.Date date = new java.util.Date(year - 1900, month, dayOfMonth, hour, minute, second);
long timestamp = date.getTime();

2 - 使用时区设置为GMT的日历

Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, second);
c.set(Calendar.MILLISECOND, 0);
long timestamp = c.getTimeInMillis();

我的问题之一是在没有混淆更多时区问题的情况下,我发现很难进行测试。

是否有使用标准 API 的明确正确方法?

更新:希望使用标准 JavaSE 得到答案。我知道 Joda-Time 很棒,但在这种情况下不可行。


FYI,那些令人头疼的旧日期时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat,现在已经成为遗留系统,被内置于Java 8和Java 9的java.time类所取代。请参阅Oracle的教程 - undefined
4个回答

4

简而言之

OffsetDateTime.of( 2018 , 1 , 23 , 12 , 34 , 56 , 0, ZoneOffset.UTC )

java.time

现代方法使用java.time类。 与麻烦的旧日期时间类不同,java.time类使用合理的编号:
  • 2018表示2018年。(没有1900年的疯狂数学。)
  • 1-12表示一月到十二月。(不是愚蠢的0-11。)
  • 1-7表示星期一至星期日,符合ISO 8601标准定义的一周。(不会因地区而异。)
  • Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒(最多九位小数)。

    如果解析字符串,则可以使用一行代码。

    Instant instant = Instant.parse( "2018-01-23T12:34:56Z" ) ;
    
    Instantjava.time 的基本构建块类,而 OffsetDateTime 类更加灵活。UTC 的偏移量从UTC本身开始定义为常量,以方便使用。
    OffsetDateTime odt = OffsetDateTime.of( 2018 , 1 , 23 , 12 , 34 , 56 , 0, ZoneOffset.UTC ) ;
    

    个人而言,我更喜欢使用片段。 在月份的位置上,您可以指定一个Month枚举对象,而不是仅仅使用整数。
    LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;  // Date-only, without time-of-day.
    LocalTime lt = LocalTime.of( 12 , 34 , 56 ) ;  // Time-of-day, without date.
    ZoneOffset offset = ZoneOffset.UTC ;
    OffsetDateTime odt = OffsetDateTime.of( ld , lt , offset ) ;
    

    关于 java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类替代了老旧的 传统 日期时间类,如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在处于 维护模式,建议迁移到 java.time 类。

    了解更多信息,请查看 Oracle 教程。并搜索 Stack Overflow 获取许多示例和说明。规范为 JSR 310

    使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序,您可以直接与数据库交换 java.time 对象。无需字符串或 java.sql.* 类。

    如何获取 java.time 类?

    ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来添加的潜在试验场。您可能会在此处找到一些有用的类,例如Interval, YearWeek, YearQuarter更多


    2

    不,除非你使用Joda-Time,否则没有其他方法,正确的方法是使用Calendar和日历API,但它很丑陋,目前没有人能做什么。


    哈哈,我猜我应该感到开心了。谢谢 :( - undefined

    1

    标准Java日期API相当不方便。考虑使用 Joda-Time

    long timestamp = new LocalDateTime(year, month, day, hour, minute, second)
        .getLocalMillis();
    

    1

    我认为这会相当不错

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
    Date date = sdf.parse("2011-12-21 12:00:00+0000");
    

    你需要自己构建日期字符串,但它很短,应该可以正常工作。并根据您的喜好创建SimpleDateFormat,重要的部分是对应于“+0000”的Z。

    这里有另一种相同方式的替代方法。

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = sdf.parse("2011-12-21 12:00:00");
    

    它带有明确的时区,并且去掉了Z。


    这看起来确实整洁、合理且易读。一旦我的变量都混在一起,可能就不那么顺利了,但我会试一试。 - undefined

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接