Java - SimpleDateFormat 格式化程序到 return 以毫秒为单位的纪元时间
Java - SimpleDateFormat formatter to return epoch time with milliseconds
我对 Java 和一般编码还很陌生 - 我有一些代码 return 是以下格式 yyyy.MM.dd HH:mm:ss:ms
的时间戳,如下所示:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
这个returns:
2017.07.19 11:42:30:423
有没有办法将上面的 "SimpleDateFormat formatter" 代码编辑为 return date/time 作为包含毫秒的纪元时间戳,以便格式化值 returned根据以下?
1500464550423
我希望我可以修改 SimpleDateFormat formatter
代码的 ("yyyy.MM.dd HH:mm:ss:sss")
部分来执行此操作。
非常感谢任何帮助或建议。
谢谢
如果您有 java.util.Date
,那么调用 getTime()
将 return 自纪元以来的毫秒数。例如:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
Date dateToBeFormatted = new Date();
// this will print a datetime literal on the above format
System.out.println(formatter.format(dateToBeFormatted));
// this will print the number of millis since the Java epoch
System.out.println(dateToBeFormatted.getTime());
这里的关键点是,为了获得自纪元以来的毫秒数,您不需要 SimpleDateFormatter
因为自纪元以来的毫秒数是 属性 Date
.
第一个建议是转向 java8 java.time API 而不是学习损坏的 java.date API
然后做:
Instant i = Instant.now();
System.out.println(i.toEpochMilli());
在你的情况下你可以这样做:
LocalDateTime myldt = LocalDateTime.parse("2017-06-14 14:29:04",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(myldt.toInstant(ZoneOffset.UTC).toEpochMilli());
请注意,一旦您使用 api 玩得越多,您就会发现更多实现同一目标的方法,最后您将结束调用 toEpochMilli
String strDate = "Jun 13 2003 23:11:52.454 UTC";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss.SSS zzz");
ZonedDateTime zdt = ZonedDateTime.parse(strDate,dtf);
System.out.println(zdt.toInstant().toEpochMilli()); // 1055545912454
你可以试试
long time = System.currentTimeMillis();
首先,检查documentation of SimpleDateFormat
。 毫秒对应的模式是大写S
,而小写s
对应秒。问题是 SimpleDateFormat
通常不会抱怨并尝试将 423
解析为秒,将此数量添加到您的结束日期(给出不正确的结果)。
无论如何,SimpleDateFormat
只是将 String
解析为 java.util.Date
或将 Date
格式化为 String
。如果你想要 epoch 毫秒值,你必须从 Date
对象中获取它:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
// parse to a date
Date date = formatter.parse(s);
// get epoch millis
long millis = date.getTime();
System.out.println(millis); // 1500475350423
问题是SimpleDateFormat
使用系统的默认时区,所以上面的最终值(1500475350423
)将等同于我系统时区的特定日期和时间(可以不同来自你的 - 仅作记录,我系统的默认时区是 America/Sao_Paulo
)。如果你想指定这个日期在哪个时区,你需要在格式化程序中设置(在调用parse
之前):
// set a timezone to the formatter (using UTC as example)
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
由此,millis
的结果将是 1500464550423
(相当于 UTC 中的特定日期和时间)。
要执行相反的操作(从毫秒值创建日期),您必须创建一个 Date
对象,然后将其传递给格式化程序(还要注意为格式化程序设置时区):
// create date from millis
Date date = new Date(1500464550423L);
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// format date
String formatted = formatter.format(date);
Java 新 date/time API
旧的 classes(Date
、Calendar
和 SimpleDateFormat
)有 lots of problems and design issues,它们正在被新的 APIs.
如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java <= 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it ).
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes 和方法 names 相同。
由于输入String
没有时区信息(只有日期和时间),首先我将它解析为一个LocalDateTime
(一个class表示没有时区的日期和时间).然后我将此 date/time 转换为特定时区并从中获取毫秒值:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// as the input string has no timezone information, parse it to a LocalDateTime
LocalDateTime dt = LocalDateTime.parse(s, formatter);
// convert the LocalDateTime to a timezone
ZonedDateTime zdt = dt.atZone(ZoneId.of("Europe/London"));
// get the millis value
long millis = zdt.toInstant().toEpochMilli(); // 1500460950423
现在的值为 1500460950423
,相当于伦敦时区的指定日期和时间。
请注意 API 使用 IANA timezones names(始终采用 Region/City
格式,如 America/Sao_Paulo
或 Europe/Berlin
)。
避免使用 3 个字母的缩写(如 CST
或 PST
),因为它们是 ambiguous and not standard.
您可以通过调用 ZoneId.getAvailableZoneIds()
.
获取可用时区列表(并选择最适合您的系统的时区)
如果要使用 UTC,也可以使用 ZoneOffset.UTC
常量。
相反,你可以获取毫秒值来创建一个 Instant,将其转换为时区并将其传递给格式化程序:
// create Instant from millis value
Instant instant = Instant.ofEpochMilli(1500460950423L);
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// convert to timezone
ZonedDateTime z = instant.atZone(ZoneId.of("Europe/London"));
// format
String formatted = z.format(formatter);
您在格式模式字符串中使用大小写有一个简单的错误(区分大小写)。更糟糕的是,您正在使用旧的和麻烦的 SimpleDateFormat
class。它的众多问题之一是它没有告诉您问题是什么。
所以我建议你改用现代Java日期和时间API(我故意逐字使用你的格式模式字符串):
String receivedTimetamp = "2017.07.19 11:42:30:423";
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:sss");
LocalDateTime dateTime = LocalDateTime.parse(receivedTimetamp, parseFormatter);
System.out.println(dateTime);
此代码抛出 IllegalArgumentException: Too many pattern letters: s
。我希望这能让你意识到你使用两个 s 表示秒,三个 s 表示几分之一秒。如果仍然不清楚,the documentation 会告诉您小写 s
是正确的秒数,而您需要大写 S
来表示分数。让我们修复:
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
现在代码打印 2017-07-19T11:42:30.423
,所以我们成功地正确解析了字符串。
要转换为毫秒,我们仍然缺少一条关键信息:应该在哪个时区解释时间戳?我认为两个明显的猜测是 UTC 和您当地的时区(我不知道)。尝试 UTC:
System.out.println(dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli());
这会产生 1500464550423
,这是您要求的数字。我想我们已经完成了。
如果您想要 JVM 的时区设置,请使用 .atZone(ZoneId.systemDefault())
而不是 .atOffset(ZoneOffset.UTC)
,但请注意该设置可能会被同一 JVM 中的其他软件 运行 更改,所以这是脆弱的。
我对 Java 和一般编码还很陌生 - 我有一些代码 return 是以下格式 yyyy.MM.dd HH:mm:ss:ms
的时间戳,如下所示:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
这个returns:
2017.07.19 11:42:30:423
有没有办法将上面的 "SimpleDateFormat formatter" 代码编辑为 return date/time 作为包含毫秒的纪元时间戳,以便格式化值 returned根据以下?
1500464550423
我希望我可以修改 SimpleDateFormat formatter
代码的 ("yyyy.MM.dd HH:mm:ss:sss")
部分来执行此操作。
非常感谢任何帮助或建议。
谢谢
如果您有 java.util.Date
,那么调用 getTime()
将 return 自纪元以来的毫秒数。例如:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
Date dateToBeFormatted = new Date();
// this will print a datetime literal on the above format
System.out.println(formatter.format(dateToBeFormatted));
// this will print the number of millis since the Java epoch
System.out.println(dateToBeFormatted.getTime());
这里的关键点是,为了获得自纪元以来的毫秒数,您不需要 SimpleDateFormatter
因为自纪元以来的毫秒数是 属性 Date
.
第一个建议是转向 java8 java.time API 而不是学习损坏的 java.date API
然后做:
Instant i = Instant.now();
System.out.println(i.toEpochMilli());
在你的情况下你可以这样做:
LocalDateTime myldt = LocalDateTime.parse("2017-06-14 14:29:04",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(myldt.toInstant(ZoneOffset.UTC).toEpochMilli());
请注意,一旦您使用 api 玩得越多,您就会发现更多实现同一目标的方法,最后您将结束调用 toEpochMilli
String strDate = "Jun 13 2003 23:11:52.454 UTC";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss.SSS zzz");
ZonedDateTime zdt = ZonedDateTime.parse(strDate,dtf);
System.out.println(zdt.toInstant().toEpochMilli()); // 1055545912454
你可以试试
long time = System.currentTimeMillis();
首先,检查documentation of SimpleDateFormat
。 毫秒对应的模式是大写S
,而小写s
对应秒。问题是 SimpleDateFormat
通常不会抱怨并尝试将 423
解析为秒,将此数量添加到您的结束日期(给出不正确的结果)。
无论如何,SimpleDateFormat
只是将 String
解析为 java.util.Date
或将 Date
格式化为 String
。如果你想要 epoch 毫秒值,你必须从 Date
对象中获取它:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
// parse to a date
Date date = formatter.parse(s);
// get epoch millis
long millis = date.getTime();
System.out.println(millis); // 1500475350423
问题是SimpleDateFormat
使用系统的默认时区,所以上面的最终值(1500475350423
)将等同于我系统时区的特定日期和时间(可以不同来自你的 - 仅作记录,我系统的默认时区是 America/Sao_Paulo
)。如果你想指定这个日期在哪个时区,你需要在格式化程序中设置(在调用parse
之前):
// set a timezone to the formatter (using UTC as example)
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
由此,millis
的结果将是 1500464550423
(相当于 UTC 中的特定日期和时间)。
要执行相反的操作(从毫秒值创建日期),您必须创建一个 Date
对象,然后将其传递给格式化程序(还要注意为格式化程序设置时区):
// create date from millis
Date date = new Date(1500464550423L);
// use correct format ('S' for milliseconds)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// format date
String formatted = formatter.format(date);
Java 新 date/time API
旧的 classes(Date
、Calendar
和 SimpleDateFormat
)有 lots of problems and design issues,它们正在被新的 APIs.
如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java <= 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes 和方法 names 相同。
由于输入String
没有时区信息(只有日期和时间),首先我将它解析为一个LocalDateTime
(一个class表示没有时区的日期和时间).然后我将此 date/time 转换为特定时区并从中获取毫秒值:
// input string
String s = "2017.07.19 11:42:30:423";
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// as the input string has no timezone information, parse it to a LocalDateTime
LocalDateTime dt = LocalDateTime.parse(s, formatter);
// convert the LocalDateTime to a timezone
ZonedDateTime zdt = dt.atZone(ZoneId.of("Europe/London"));
// get the millis value
long millis = zdt.toInstant().toEpochMilli(); // 1500460950423
现在的值为 1500460950423
,相当于伦敦时区的指定日期和时间。
请注意 API 使用 IANA timezones names(始终采用 Region/City
格式,如 America/Sao_Paulo
或 Europe/Berlin
)。
避免使用 3 个字母的缩写(如 CST
或 PST
),因为它们是 ambiguous and not standard.
您可以通过调用 ZoneId.getAvailableZoneIds()
.
如果要使用 UTC,也可以使用 ZoneOffset.UTC
常量。
相反,你可以获取毫秒值来创建一个 Instant,将其转换为时区并将其传递给格式化程序:
// create Instant from millis value
Instant instant = Instant.ofEpochMilli(1500460950423L);
// use correct format ('S' for milliseconds)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
// convert to timezone
ZonedDateTime z = instant.atZone(ZoneId.of("Europe/London"));
// format
String formatted = z.format(formatter);
您在格式模式字符串中使用大小写有一个简单的错误(区分大小写)。更糟糕的是,您正在使用旧的和麻烦的 SimpleDateFormat
class。它的众多问题之一是它没有告诉您问题是什么。
所以我建议你改用现代Java日期和时间API(我故意逐字使用你的格式模式字符串):
String receivedTimetamp = "2017.07.19 11:42:30:423";
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:sss");
LocalDateTime dateTime = LocalDateTime.parse(receivedTimetamp, parseFormatter);
System.out.println(dateTime);
此代码抛出 IllegalArgumentException: Too many pattern letters: s
。我希望这能让你意识到你使用两个 s 表示秒,三个 s 表示几分之一秒。如果仍然不清楚,the documentation 会告诉您小写 s
是正确的秒数,而您需要大写 S
来表示分数。让我们修复:
DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
现在代码打印 2017-07-19T11:42:30.423
,所以我们成功地正确解析了字符串。
要转换为毫秒,我们仍然缺少一条关键信息:应该在哪个时区解释时间戳?我认为两个明显的猜测是 UTC 和您当地的时区(我不知道)。尝试 UTC:
System.out.println(dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli());
这会产生 1500464550423
,这是您要求的数字。我想我们已经完成了。
如果您想要 JVM 的时区设置,请使用 .atZone(ZoneId.systemDefault())
而不是 .atOffset(ZoneOffset.UTC)
,但请注意该设置可能会被同一 JVM 中的其他软件 运行 更改,所以这是脆弱的。