Java将日期转换为纪元值会产生错误输出

时间:2014-08-13 02:30:20

标签: java linux date ubuntu epoch

我正在尝试将以下日期时间字符串对象转换为unix纪元时间戳值。但是,当我运行该程序时,我注意到它生成了一个1404461110000的纪元值,当我检查我的ubuntu unix机器是在8月7日星期三18:06:40然而实际上我正在通过2014年7月4日04-07: 05:10。我的ubuntu机器上有美国/多伦多的时区,但我觉得这不重要吗?

Java代码:

            long epoch = 0;
            String str = "2014-07-04 04:05:10";   // UTC

            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date datenew = df.parse(str);
            epoch = datenew.getTime();

            System.out.println(epoch); // prints 1404461110000

Ubuntu Linux 14.04

date -d@1404461110000

显示= 8月7日星期三18:06:40 EDT 46475

4 个答案:

答案 0 :(得分:5)

问题是,在Java中调用getTime()时,您并未处理unix timestamp。自时间以来,Unix时间戳以表示,而自epoch(1970年1月1日)以来,您从Java获得的值毫秒,因此差异。

必须是:

epoch = datenew.getTime() / 1000;

这应该可以让你至少接近10000年。如果您在此之后仍然看到差异,则与时区相关,并且可以通过在DateFormat实例上指定时区来适应。

答案 1 :(得分:1)

您需要告诉Java时间戳是UTC,而不只是添加关于它的评论。

long epoch = 0;
String str = "2014-07-04 04:05:10";   // UTC

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC")); // assume UTC
Date datenew = df.parse(str);
epoch = datenew.getTime();

System.out.println(epoch);

答案 2 :(得分:1)

java.time

旧的日期时间 API(java.util 日期时间类型及其格式类型,SimpleDateFormat 等)已经过时且容易出错。建议完全停止使用,改用java.timemodern date-time API*

使用现代 API java.time 的解决方案:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        String str = "2014-07-04 04:05:10"; // UTC

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse(str, dtf);
        ZonedDateTime zdtUtc = ldt.atZone(ZoneId.of("Etc/UTC"));
        Instant instant = zdtUtc.toInstant();
        long epochMillis = instant.toEpochMilli();
        long epochSeconds = TimeUnit.SECONDS.convert(epochMillis, TimeUnit.MILLISECONDS);
        System.out.println(epochSeconds);

        // Corresponding date-time in America/Toronto
        ZonedDateTime zdtToronto = instant.atZone(ZoneId.of("America/Toronto"));
        System.out.println(zdtToronto);
    }
}

输出:

1404446710
2014-07-04T00:05:10-04:00[America/Toronto]

modern date-time API 中详细了解 java.timeTrail: Date Time*

一些重要的注意事项:

  1. Unix time 指定自纪元以来的秒数。
  2. 如果有可用的 OOTB(开箱即用)API,我们应该避免自己执行计算,例如TimeUnit#convert

* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 3 :(得分:0)

约达时间

仅供参考,这是相同类型的代码,但在Joda-Time 2.4中完成。 Java 8中的新java.time package(受Joda-Time启发)可以以类似的方式使用。

java.util.Date和.Calendar类非常麻烦。避免他们。使用上面提到的两个库中的任何一个。

示例代码

您的输入字符串接近标准ISO 8601格式,但不完全,错过了中间的TUTC的偏移量。 Joda-Time有一个内置的格式化程序,用于在ISO 8601中进行解析/生成。因此,不要定义我们自己的格式化程序,让我们稍微调整输入字符串,插入T

String inputRaw = "2014-07-04 04:05:10";   // UTC
String input = inputRaw.replace( " ", "T" ); // Convert to standard ISO 8601 format.

然后我们将告诉DateTime构造函数将String解析为UTC(零偏移)。与java.util.Date不同,DateTime知道自己指定的时区。

DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );

轻松适应多伦多时间,乐趣或调试/健全检查。

DateTime dateTimeToronto = dateTimeUtc.withZone( DateTimeZone.forID( "America/Toronto" ) );

与java.util.Date一样,自UTC时代(1970年初)以来,Joda-Time内部跟踪时间为milliseconds。这意味着使用64位long而不是通常的32位int。 (顺便说一句,java.time跟踪nanoseconds。)所以,如果我们需要秒 - 自 - unix-epoch,除以一千。

long millisecondsSinceEpoch = dateTimeUtc.getMillis();  // Use a "long", not "int".
long secondsSinceEpoch = ( millisecondsSinceEpoch / 1000L );

转储到控制台。

System.out.println( "input: " + input );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeToronto: " + dateTimeToronto );
System.out.println( "millisecondsSinceEpoch: " + millisecondsSinceEpoch );
System.out.println( "secondsSinceEpoch: " + secondsSinceEpoch );

跑步时。

input: 2014-07-04T04:05:10
dateTimeUtc: 2014-07-04T04:05:10.000Z
dateTimeToronto: 2014-07-04T00:05:10.000-04:00
millisecondsSinceEpoch: 1404446710000
secondsSinceEpoch: 1404446710