Java 如何将时间戳字符串转换为历元时间?
我的时间戳格式为Java 如何将时间戳字符串转换为历元时间?,java,timestamp,epoch,java-time,datetime-parsing,Java,Timestamp,Epoch,Java Time,Datetime Parsing,我的时间戳格式为2017-18-08 11:45:30.345 我想将其转换为大纪元时间,因此我将执行以下操作: String timeDateStr = "2017-18-08 11:45:30.345"; DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM HH:mm:ss.SSS"); ZonedDateTime zdt = ZonedDateTime.parse(timeDateStr, dtf);
2017-18-08 11:45:30.345
我想将其转换为大纪元时间,因此我将执行以下操作:
String timeDateStr = "2017-18-08 11:45:30.345";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM HH:mm:ss.SSS");
ZonedDateTime zdt = ZonedDateTime.parse(timeDateStr, dtf);
System.out.println(zdt.toInstant().toEpochMilli());
我得到以下错误:
java.time.format.DateTimeParseException:无法分析文本“2017-18-08 11:45:30.345”:无法从TemporalAccessor获取ZonedDateTime
我也尝试了不同的格式,但仍然有错误 更正了有关yyyy dd MM的代码。此外,分钟值可能为1-59,而不是60。你提供了60英镑。这是解决这个问题的另一个简单方法。只需使用DateFormat类
String timeDateStr = "2017-18-08 12:59:30.345";
DateFormat df = new SimpleDateFormat("yyyy-dd-MM hh:mm:ss.SSS", Locale.ENGLISH);
try {
Date d = df.parse(timeDateStr);
System.out.println(d.toInstant().toEpochMilli());
} catch (ParseException e) {
e.printStackTrace();
}
注意:问题输入了2017-18-08 12:60:30.345
(分钟字段中有60
),然后(时间从12:60
更改为11:45
),但我决定继续讨论原始输入(12:60
),因为它也适用于编辑的版本(11:45
)
ZonedDateTime
需要时区或偏移量,但输入的字符串中没有它(它只有日期和时间)
输入中还有其他详细信息:
- 分钟值是
60
,这是不被接受的:有效值是从0到59(实际上有一种方法可以接受,请参阅下面的“宽松解析”)
hh
是唯一的,因此它还需要完全解析AM/PM指示符。因为没有,所以应该使用HH
模式
因此模式必须是yyyy-dd-MM HH:MM:ss.SSS
,输入不能将60
作为分钟值(除非使用宽松解析,我将在下面解释),并且不能直接解析为ZoneDateTime
,因为它没有时区/偏移指示器
另一种方法是将其解析为LocalDateTime
,然后定义此日期所在的时区/偏移量。在下面的示例中,我假设它位于:
这将输出:
1503061170345
这相当于中的2017-18-08 12:59:30.345
如果希望日期位于其他时区,可以使用ZoneId
类:
// get the LocalDateTime in some timezone
ZonedDateTime z = dt.atZone(ZoneId.of("Europe/London"));
System.out.println(z.toInstant().toEpochMilli());
String timeDateStr = "2017-18-08 12:60:30.345";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM HH:mm:ss.SSS")
// use lenient parsing
.withResolverStyle(ResolverStyle.LENIENT);
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(timeDateStr, dtf);
输出为:
150305757345
请注意,结果是不同的,因为相同的本地日期/时间在每个时区代表不同的瞬间
(在世界各地,本地日期/时间2017-18-08 12:59:30.345发生在不同的瞬间)
还要注意,API使用的格式(始终为地区/城市
,如美国/圣保罗
或欧洲/柏林
)。
避免使用三个字母的缩写(如CST
或PST
),因为它们是
通过调用ZoneId.getAvailableZoneIds()
,可以获得可用时区的列表(并选择最适合您的系统的时区)
您也可以将系统的默认时区与ZoneId.systemDefault()
一起使用,但即使在运行时,也可以在不事先通知的情况下更改,因此最好明确使用特定的时区
还可以选择将LocalDateTime
转换为(如-05:00
或+03:00
):
输出将相当于偏移量+03:00
(UTC前3小时)中的本地日期/时间:
1503050370345
宽松解析
同样,您可以在分钟字段中使用宽松解析来接受60
(使用java.time.format.ResolverStyle
类):
在这种情况下,将60分钟调整到下一个小时,LocalDateTime
将为:
2017-08-18T13:00:30.345
夏时制
如果您决定使用UTC或固定偏移量(使用ZoneOffset
class),则可以忽略此部分
但是,如果您决定使用时区(使用ZoneId
class),您还必须注意这些问题。我将以我居住的时区为例(美国/圣保罗
)
在圣保罗,DST从2017年10月15日开始:午夜,时钟从午夜向前移动1小时至凌晨1点。所以00:00到00:59之间的所有本地时间都不存在于这个时区中。如果在此时间间隔内创建本地日期,则会将其调整到下一个有效时刻:
ZoneId zone = ZoneId.of("America/Sao_Paulo");
// October 15th 2017 at midnight, DST starts in Sao Paulo
LocalDateTime d = LocalDateTime.of(2017, 10, 15, 0, 0, 0, 0);
ZonedDateTime z = d.atZone(zone);
System.out.println(z);// adjusted to 2017-10-15T01:00-02:00[America/Sao_Paulo]
DST结束时:2018年2月18日午夜,时钟倒转1小时,从午夜到17日晚23点。因此,从23:00到23:59的所有本地时间都存在两次(在DST和非DST中),您必须决定您想要哪一次:
// February 18th 2018 at midnight, DST ends in Sao Paulo
// local times from 23:00 to 23:59 at 17th exist twice
LocalDateTime d = LocalDateTime.of(2018, 2, 17, 23, 0, 0, 0);
// by default, it gets the offset before DST ends
ZonedDateTime beforeDST = d.atZone(zone);
System.out.println(beforeDST); // before DST end: 2018-02-17T23:00-02:00[America/Sao_Paulo]
// get the offset after DST ends
ZonedDateTime afterDST = beforeDST.withLaterOffsetAtOverlap();
System.out.println(afterDST); // after DST end: 2018-02-17T23:00-03:00[America/Sao_Paulo]
请注意,DST结束前后的日期具有不同的偏移量(-02:00
和-03:00
)。这会影响Epochmili的值
您必须检查DST何时在您选择的时区开始和结束,并相应地检查调整。刚才我在nagendra547的答案中做了一点更改
请参考以下代码:-
String timeDateStr = "2017-18-08 12:59:30.345";
DateFormat df = new SimpleDateFormat("yyyy-dd-mm hh:mm:ss.SSS", Locale.ENGLISH);
try {
Date d = df.parse(timeDateStr);
System.out.println(d.toInstant().toEpochMilli());
} catch (ParseException e) {
e.printStackTrace();
}
您的代码将因以下3个原因失败
您的日期字符串(2017-18-08 12:60:30.345
)与您使用的格式设置程序不匹配。它应该是yyyy-MM-dd HH:MM:ss.SSS而不是yyy-dd-MM HH:MM:ss.SSS
分钟的范围是(0-59),60不在此范围内
即使您已基于上述点更正了代码,它也不会在ZoneDateTime
中运行。因此,您需要在之前创建一个LocalDateTime
,然后将一个ZoneId
传递给它
代码应如下所示:
String timeDateStr = "2017-18-08 12:59:30.345";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM HH:mm:ss.SSS");
LocalDateTime date = LocalDateTime.parse(timeDateStr, dtf);
ZonedDateTime zdt = date.atZone(ZoneId.of("Europe/London"));
System.out.println(zdt.toInstant().toEpochMilli());
这是打字错误,请检查更新的问题。谢谢你的指点。@Assafs不,不是唯一的错误。也请看一看模式符号“h”。@User7723337分钟是60?您解决了这个问题吗?ZonedDateTime在这个模式没有时区信息时有效吗?您是唯一一个看到h对h错误的回答者(因此向上投票)。关于mi
String timeDateStr = "2017-18-08 12:59:30.345";
DateFormat df = new SimpleDateFormat("yyyy-dd-mm hh:mm:ss.SSS", Locale.ENGLISH);
try {
Date d = df.parse(timeDateStr);
System.out.println(d.toInstant().toEpochMilli());
} catch (ParseException e) {
e.printStackTrace();
}
String timeDateStr = "2017-18-08 12:59:30.345";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM HH:mm:ss.SSS");
LocalDateTime date = LocalDateTime.parse(timeDateStr, dtf);
ZonedDateTime zdt = date.atZone(ZoneId.of("Europe/London"));
System.out.println(zdt.toInstant().toEpochMilli());