【问题标题】:Issue is converting seconds to date/time in Java问题是将秒转换为 Java 中的日期/时间
【发布时间】:2018-12-27 08:41:19
【问题描述】:

我想在以下 java 代码中将 1969 年 12 月 31 日 7 PM 的秒数转换为日期/时间。

package sampProp;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.TimeZone;


public class sample 
{    
    public static void main(String args[])  
    {

     //Here 1373605580 is the number os secs from DEC 31ST 1969 7 PM
     long millisecs = (long)(1373605580) *1000;

     DateFormat df = new SimpleDateFormat("MM/dd/yyyy_HH:mm:ss a");

     df.setTimeZone(TimeZone.getTimeZone("EST"));

     Date d1 = new Date(millisecs);

     String formattedDate = df.format(d1); 

     System.out.println("Formatted date is "+formattedDate);

    } 
}

我在 AIX 服务器上运行代码。

我的开发服务器给出的值 07/12/2013_00:06:20 是正确的,但我的生产服务器给出的 07/12/2013_01:06:20 是不正确的。

这怎么可能。我该如何纠正这一点。

我的开发服务器的 java-version 输出是:

java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pap64dev-20071008 (SR6))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 AIX ppc64-64 j9vmap6423-20071007 (JIT enabled)
J9VM - 20071004_14218_BHdSMr
JIT  - 20070820_1846ifx1_r8
GC   - 200708_10)
JCL  - 20071008

而我的生产服务器的 java-version 输出是:

java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pap64dev-20080315 (SR7))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 AIX ppc64-64 j9vmap6423-20080315 (JIT enabled)
J9VM - 20080314_17962_BHdSMr
JIT  - 20080130_0718ifx2_r8
GC   - 200802_08)
JCL  - 20080314

【问题讨论】:

  • 您在两台机器上分别安装了哪些 JDK 或 JRE 版本?另外,您知道不推荐使用三字母时区代码,对吧?
  • 你的用例是什么?你可以改用 Joda-Time 吗? joda.org/joda-time
  • 当似乎没有任何问题时,您不能总是只推荐 Joda-Time 作为解决所有问题的方法......我看不出这段代码有什么问题,所以弄清楚它会很有趣实际问题。
  • 我最好的猜测是,您的两个 Java 版本具有从“EST”(在夏令时规则方面不明确)到实时时区(例如 America/New_York、America/Kentucky)的不同映射/Louisville 等),每个规则都包含一组夏令时规则,以及与 GMT 的偏移量。使用时区的全名总是最安全的。
  • 不确定您当地的时区,但在美国,我们刚刚从夏令时回滚到标准时间。这会影响您的测试吗?祝你好运。

标签: java aix


【解决方案1】:

是不是因为你的时区没有在你的服务器上正确设置?

检查这个问题并回答:java incorrect timezone

检查开发服务器和生产服务器中 JVM 的时区。

编辑

正如许多人所说:它不应该来自那个,它仍然很奇怪,并且您的两个服务器之间的配置看起来非常相似(仍然:JVM 不一样)。应该有区别,所以检查 JVM 参数和系统变量并查看时区似乎是我的首选。

重新编辑:

正如大卫所说:这是一个关于节省时间的错误:

这里是链接:http://www.coderanch.com/t/458357/java/java/AIX-Timezone-Java-showing-hour

还有来自 IBM 的链接:http://www-01.ibm.com/support/docview.wss?uid=swg21250503

我引用:

2006 年,EST 时区标识符的含义在 奥尔森数据库。从历史上看,EST 指的是美国东部 标准时间并针对夏令时进行了调整。下列的 更改,EST 指的是东部标准时间,没有调整 夏令时。还引入了一个新的标识符 EST5EDT 与原始 EST 标识符具有相同的含义。 EST5EDT 因此指的是美国东部标准时间,并使得 调整夏令时。

避免这些问题的最佳方法是使用长时区 America/New_York 等标识符。

如果您无法更改应用程序以使用长时区 标识符,您可以设置系统属性 ibm.dst.compatibility 或 sun.timezone.ids.oldmapping 以改变对 EST 或 MST 的解释。

【讨论】:

  • 理论上这应该无关紧要,因为他没有对服务器本身的时区进行格式化。
  • 有新的 Date(millis) 并且 Date 应该有一个时区,具体取决于 JVM 时区。
  • 这不太可能是正确的答案。问题中的代码甚至不应该查看服务器的时区。
  • 这完全是错误的zenbeni。日期根本没有时区信息。
  • 我的错,你是对的。它只是解析日期的 JVM。通过服务器配置检查差异仍然不是一个坏主意。
【解决方案2】:

tl;博士

  • 使用 java.time
  • 指定您希望/预期的时区

例如:

Duration.between( 
    Instant.EPOCH , 
    Instant.now() 
)

避免使用旧的日期时间类

与最早版本的 Java 捆绑在一起的可怕的旧日期时间类在几年前被 java.time 类所取代。

要查看特定地区(时区)人们使用的挂钟时间,请使用ZonedDateTime。暂时使用 UTC,使用Instant

使用正确的时区名称

Continent/Region 的格式指定proper time zone name,例如Europe/ParisAfrica/CasablancaPacific/Auckland。切勿使用 2-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

ZoneId

从 1969 年 12 月 31 日美国东部标准时间下午 7 点开始的 os 秒数

首先,EST 不是时区,如上所述。我假设您的意思是北美东海岸的时区,例如America/New_York

ZoneId z = ZoneId.of( "America/New_York" ) ;  

ZonedDateTime

在一个时区中,我们需要ZonedDateTime

ZonedDateTime zdt = ZonedDateTime.of( 1969 , 12 , 31 , 17 , 0 , 0 , 0 , z ) ;

zdt.toString(): 1969-12-31T17:00-05:00[美国/纽约]

Duration

要将时间跨度表示为秒数,请使用Duration 类。

ZonedDateTime now = ZonedDateTime.now( z ) ;
Duration d = Duration.between( zdt , now ) ;

now.toString(): 2018-12-26T19:32:08.136846-05:00[America/New_York]

d.toString(): PT429410H32M8.136846S

要求以整秒为单位的整个时间跨度。

long wholeSeconds = d.getSeconds();

整秒:1545877928

Instant

我注意到您的起源时间是 1970 年之前的几个小时,美国东部标准时间恰好是 UTC 时间 1970 年的第一刻。那一刻,1970-01-01T00:00:00Z,是一个常见的 epoch reference,众所周知作为Unix Time。那一刻也是 java.time 类使用的纪元参考。

我怀疑你落入了狭隘思维的陷阱,从你自己的个人时区的角度来看。这对程序员来说是不明智的。当程序员在工作时,你应该几乎一直在思考 UTC,以 UTC 存储,以 UTC 登录,并以 UTC 交换数据。仅在业务逻辑需要或用户在用户界面中期望时应用时区。

要以 UTC 跟踪时刻,请使用 Instant。对于 1970-01-01T00:00:00Z 的纪元引用,使用常量Instant.EPOCH

Duration d = Duration.between( Instant.EPOCH , Instant.now() ) ;

关于java.time

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

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

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

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

从哪里获得 java.time 类?

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

【讨论】:

  • 很好的答案。现在请您用“现代工具”重写原始程序以显示它们的优越性,并表明它们可以在 Aix5.x 和 IbmJava1.5 上运行
猜你喜欢
  • 1970-01-01
  • 2011-05-22
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多