【问题标题】:How to calculate difference between UTC time and local time如何计算UTC时间和本地时间之间的差异
【发布时间】:2017-01-11 16:22:17
【问题描述】:

我正在尝试从 UTC 时间戳获取本地时间并计算偏移量。 我有一个 UTC 时间 =1484063246 这是我的代码。

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       dateFormat.setTimeZone(TimeZone.getTimeZone("CET"));
       String formattedDate = dateFormat.format(new Date(1484063246L * 1000L)); 

formattedDate 以日期格式返回。如何根据这些值计算 UTC 时间和本地时间之间的差异。如何根据服务器运行的位置而不是硬编码“CET”来设置TimeZone。

【问题讨论】:

标签: java date


【解决方案1】:

如果我理解您的问题,您可以这样做 (JSE >= 1.8):

import java.time.Instant;
import java.time.ZoneId;

Instant instant = Instant.ofEpochMilli(1484063246L * 1000L);

// You can use this if you already have a Date object
// Instant instant = dateInstance.toInstant();

// You can use this for current offset
// Instant instant = Instant.now(); 

ZoneId.systemDefault().getRules().getOffset(instant);

systemDefault() 返回系统默认(本地)ZoneId,getOffset(instant) 返回指定时刻从该区域到 UTC 的偏移量。

例如

+01:00Europe/Berlin

-02:30Canada/Newfoundland

Z for UTC(注意任何数字转换!!)

详情请查看official docs

编辑:删除了 Date 类的使用,因为它可以避免导入(正如 Basil Bourque 的回答所暗示的那样)。顺便说一句,Date 类是旧的,但是一个非常简单且从未被弃用的类。事实上,它是纯毫秒级的轻量级抽象。

【讨论】:

  • @madhu 如果成功了,可以标记为正确答案:)
  • 为什么是随机数或秒而不是 Instant.now() ?
  • @Ewoks 来自 OP 的问题。您也可以在 cmets 中找到 Instant.now() :) 所讨论的偏移量可能会随时间变化,您可能有兴趣在特定时刻找到它,
【解决方案2】:

以毫秒为单位获取当前时间戳并从 1484063246 中减去。 从下面的示例开始。 您还需要检查偏移量是否为正/负。

    long now = System.currentTimeMillis();
    long offset = now - 1484063246L * 1000;
    Date date = new Date(offset);
    DateFormat df = new SimpleDateFormat("HH:mm:ss");
    System.out.println(df.format(date));

【讨论】:

    【解决方案3】:

    tl;博士

    ZoneId.of( "Europe/Paris" )
          .getRules()
          .getOffset( 
              Instant.ofEpochMilli( 1_484_063_246L ) 
          ).getTotalSeconds()
    

    小心“本地”这个词

    在Java 日期时间类中,LocalDateLocalTimeLocalDateTime 中的单词local 表示任何 位置,没有特定位置。这些类故意没有时区或偏移量的概念。绝对不是在这个问题的上下文中你想要的。

    避免使用旧的日期时间类

    Answer by Linuslabo 是正确的,并且使用 java.time 类朝着正确的方向前进,但不必要地涉及旧的遗留 java.util.Date 类。

    避免使用旧的旧日期时间类(DateCalendarSimpleDateFormat 等),因为它们已被证明令人困惑、设计不佳且麻烦。现在被java.time 类所取代。

    使用 java.time

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

    epoch 以来,您的输入似乎是milliseconds 的计数。

    请注意,Java 允许在数字文字中使用下划线,以便于人类阅读。

    Instant instant = Instant.ofEpochMilli( 1_484_063_246L );
    

    您可以将其调整为时区以查看某些地区的wall-clock time。以continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTCETIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

    ZoneId zoneId = ZoneId.of( "Europe/Paris" );
    ZonedDateTime zdt = instant.atZone( zoneId );
    

    您可以通过ZoneRulesZoneId 询问offset-from-UTC (ZoneOffset),这似乎是您问题的重点。由于Daylight Saving Time (DST) 等异常,偏移量会随时间变化。时区是过去、现在和近期的偏移量的集合。因此,当向区域询问偏移量时,您必须指定一个时间点。

    ZoneOffset zoneOffset = zoneId.getRules().getOffset( instant );
    

    如果需要,您可以获取偏移量as a total number of seconds

    int offsetInSeconds = zoneOffset.getTotalSeconds() ;
    

    关于java.time

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

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

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      猜你喜欢
      • 2023-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多