将日期转换为纪元Java

时间:2018-03-01 08:40:02

标签: java datetime simpledateformat epoch datetime-parsing

我想将2018-02-21 15:47:35 UTC转换为纪元UTC表格。我们该怎么做呢?我现在在PST。

SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS");

df.setTimeZone(TimeZone.getTimeZone("UTC"));
date = df.parse(dateString).getTime();

上面的代码应该返回自January 1, 1970, 00:00:00 GMT以来的毫秒数,但我得到的值不正确。

4 个答案:

答案 0 :(得分:3)

您的代码唯一的问题是DateFormat

请检查。 https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

    String dateString = "2018-02-21 15:47:35";
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = df.parse(dateString);
    long time = date.getTime();

    System.out.println(time);
    System.out.println(new Date(time));
    System.out.println(date);

我在PKT,所以输出会有所不同......

1519228055000
Wed Feb 21 20:47:35 PKT 2018
Wed Feb 21 20:47:35 PKT 2018

答案 1 :(得分:3)

预计:2018-02-21 15:47:35 UTC相当于自1970年1月1日0:00 UTC世纪以来的1 519 228 055 000毫秒。

观察:您在问题中的代码为1 514 818 800 035.所以它是4 409 254 965毫秒关闭,超过51天。

解决方案

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    date = LocalDateTime.parse("2018-02-21 15:47:35", dtf)
            .atOffset(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli();

这给出了正确的1 519 228 055 000。

出了什么问题?

SimpleDateFormat的许多麻烦特征之一是,使用默认设置,如果指定了不正确的格式模式字符串,它通常会给你一个不正确的结果,并假装一切都很好。我在我的代码片段中使用的现代Java日期和时间API正在尝试更难以弄清楚模式何时没有意义并告诉你它在某种程度上是错误的。例如,让我们尝试使用现代DateTimeFormatter

的格式模式
    final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:MM:SS");
    LocalDateTime.parse(dateString, dtf);

这将抛出java.time.format.DateTimeParseException: Text '2018-02-21 15:47:35' could not be parsed at index 14。索引14是字符串中的47,它应该是分钟。显然,47与格式中的MM不匹配。如果您还没有想出来,请查看文档。它说大写M代表“一年中的月份”。那么格式化程序试图告诉你的是一年中没有47个月。在文档中,您还会发现“小时”的小写m。当您更正格式模式字符串中字母的大小写时,您将收到其他例外情况,直到您最终得到yyyy-MM-dd HH:mm:ssuuuu-MM-dd HH:mm:ss(小写yyyy是年份或时代{{{ 1}}是签名年份,在0年后都工作多年。

<强>链接

答案 2 :(得分:1)

也可以通过java8时间库完成:

String dateString = "2018-02-21 15:47:35";

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);

dateTimeFormatter.withZone(ZoneId.of("UTC"));
LocalDateTime parsedDateTime = LocalDateTime.from(dateTimeFormatter.parse(dateString));
ZonedDateTime timeAtYourZone = parsedDateTime.atZone(ZoneId.systemDefault());

System.out.println(timeAtYourZone.toInstant().toEpochMilli());
System.out.println(timeAtYourZone);

答案 3 :(得分:0)

您的模式必须为yyyy-MM-dd HH:mm:ss,其他答案告诉您:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

我只是想补充一些细节。

首先,看一下javadoc中的模式描述:https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

请注意,小写 y 与大写 Y 不同(小写是年份,而大写是week year - 2个不同的字段完全不同的定义)

另请注意,大写 D 是一年中的某一天,而月份的日期(您想要的)是小写 d 。大写 M 是月份,而小写 m 是小时。

大写 S 是毫秒字段,而秒由小写 s 表示。

并且SimpleDateFormat的设计没有帮助:即使月份字段( MM )出现两次,该类也会尝试解析字符串模式,而分钟字段不会出现(并且它被设置为默认值零 - 所有在幕后,没有任何警告,根本没有错误迹象)。

结论:总是阅读文档: - )

对于Java 8或更高版本,请考虑使用新的日期API,它更好,因为它没有所有这些幕后的东西:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                           .withZone(ZoneOffset.UTC);
long epochMilli = Instant.from(fmt.parse("2018-02-21 15:47:35")).toEpochMilli();

如果您使用YYYY-MM-DD HH:MM:SS这样的模式,此API也会抛出异常,因为它会尝试将分钟值47解析为一个月(因为大写 MM 将在相应的位置),47不是有效月份。