2015-06-23 96 views
-1

我有一个要求将日期解析为毫秒。这是我如何做的。日期计算的差异Java SimpleDateFormat

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

     public void setTime(String date) { 
     try { 
      sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 
      this.time = sdf.parse(date).getTime(); 
     } catch (ParseException e) { 
       e.printStackTrace(); 
     } 

这是我的服务器中的问题。

例如,对于给定输入日期“2015-06-20T01:57:13Z”,我得到的产值为1592618233000毫秒,但是,预期值应为1434765433000.

分析,我发现这个问题157852800000毫秒的差值在转换成“Thu Jan 01 1975 05:30:00 GMT + 0530(IST)”日期。

我看到157852800000 ms正在添加到我的服务器中的几个日期。这里没有代码问题。我正在使用上面显示的代码。当我在本地机器上运行它时,它工作得很好。另外,我的服务器中的这种情况不会一直发生。

请指教。

+0

它使用机器时间,如果你不建立一个区域 –

回答

0

也许这是并发问题。 SimpleDateFormat不是线程安全的。因此,每次使用时都要创建它,或者同步对它的访问并检查是否可以解决您的问题。

+0

但是为什么它每次只增加jan 01 1975。从哪里挑选此值,以及在哪些情况下会将此日期添加到输入日期。请告知 – skanda

1

它可能会或可能不会导致你的问题在这里,但一般来说你不应该使SimpleDateFormat一个静态字段。这是因为这个类是有状态的,因此不是线程安全的;当多个线程访问同一个实例时,可能会出现意外的结果。

+0

了解。但为什么每次只增加1月1日1975。从哪里挑选此值,以及在哪些情况下会将此日期添加到输入日期。 – skanda

0

SimpleDateFormat不是线程安全的。这可能是多个线程访问同一个simpledateformat实例的可能性。一般不建议将其设为静态。每个实例都应该有它自己的simpledateformat实例。

+0

谢谢srijan。你能否就我上面的评论提出建议? – skanda

0

显然你的一端出了问题。

这是我的代码版本。使用Java 8更新45.

try { 
    String input = "2015-06-20T01:57:13Z"; 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

    sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 
    java.util.Date date = sdf.parse(input); 
    long millisSinceEpoch = date.getTime(); 

    System.out.println("millis: " + millisSinceEpoch); 

} catch (ParseException ex) { 
    // Handle exception 
} 

运行时。

millis: 1434765433000 

我收到了您的预期结果。

也许这个问题与你的SimpleDateFormat实例的不正确使用相关,如同静态一样,正如其他评论和答案中指出的一样。

顺便说一句,java.util.Date/.Calendar类是非常麻烦的。他们现在是由两种取代:

这两个框架默认支持输入字符串的ISO 8601格式。

而这两个框架都将时区分配给它们各自的日期 - 时间对象。

Joda-Time

这是代码Joda-Time 2.8.1。搜索StackOverflow了解更多示例和讨论。

String input = "2015-06-20T01:57:13Z"; 
DateTimeZone zone = DateTimeZone.forID("Asia/Kolkata"); 
DateTime dateTimeKolkata = new DateTime(input , zone); 
DateTime dateTimeUtc = dateTimeKolkata.withZone(DateTimeZone.UTC); 
long millisSinceEpoch = dateTimeKolkata.getMillis(); 

转储到控制台。

System.out.println("dateTimeKolkata: " + dateTimeKolkata); 
System.out.println("dateTimeUtc: " + dateTimeUtc); 
System.out.println("millisSinceEpoch: " + millisSinceEpoch); 

运行时。

dateTimeKolkata: 2015-06-20T07:27:13.000+05:30 
dateTimeUtc: 2015-06-20T01:57:13.000Z 
millisSinceEpoch: 1434765433000 

java.time

代码java.time将在概念上面看到的乔达,时间码类似,不同之处在于java.time使用工厂方法,而不是“新”的构造。

查看此问题的Parse ISO timestamp using Java 8 java.time api (standard edition only)代码示例。

避免计数纪元以来

我建议避免(在你的情况毫秒)直接与计数从历元的工作只要有可能。使用体面的日期时间框架并坚持其智能对象。你是否使用原始字节数组而不是String实例处理文本?相同的逻辑适用于日期时间值。