问题描述
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss`ZZ:ZZ`");
sdf.parse("2020-12-16T16:27:57+00:00");
我不确定日期的格式,但我很确定它是 yyyy-MM-dd'T'HH:mm:ssZZ:ZZ
或类似的格式。我在猜 z 来自
https://help.sumologic.com/03Send-Data/Sources/04Reference-Information-for-Sources/Timestamps%2C-Time-Zones%2C-Time-Ranges%2C-and-Date-Formats
什么是正确的格式以及如何将其转换为毫秒?
我也试过
Instant instant = Instant.parse("2020-12-16T16:27:57+00:00");
我从我的世界 json 文件中抓取它。我拒绝使用 joda 时间,因为我的世界最初是用 java 5 编写的,并且没有使用 joda 时间来做。他们后来更新到 java 7
解决方法
OffsetDateTime.parse( "2020-12-16T16:27:57+00:00" )
切勿使用 SimpleDateFormat
或多年前被现代 java.time 类取代的其他糟糕的日期时间类。
java.time 类在解析/生成表示日期时间值的字符串时默认使用标准 ISO 8601 格式。您的输入采用其中一种标准格式。所以不需要指定格式模式。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
要了解更多信息,请参阅 Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为 JSR 310。
现在位于 Joda-Time 的 maintenance mode 项目建议迁移到 java.time 类。
您可以直接与您的数据库交换 java.time 对象。使用符合 JDBC driver 或更高版本的 JDBC 4.2。不需要字符串,不需要 java.sql.*
类。 Hibernate 5 和 JPA 2.2 支持 java.time。
从哪里获取 java.time 类?
-
Java SE 8、Java SE 9、Java SE 10、Java SE 11 和更高版本 - 具有捆绑实现的标准 Java API 的一部分。
- Java 9 带来了一些小功能和修复。
-
Java SE 6 和 Java SE 7
- 大部分 java.time 功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7。
-
Android
- 更高版本的 Android (26+) 捆绑了 java.time 类的实现。
- 对于早期的 Android (API desugaring 的进程带来了最初未内置于 Android 中的 subset of the java.time 功能。
- 如果脱糖不能满足您的需求,ThreeTenABP 项目会将 ThreeTen-Backport(上文提到的)适配到 Android。见How to use ThreeTenABP…。
想通了
* parse them zula times. example: 2010-09-18T21:35:15.000Z
*/
public static long parseZTime(String strTime)
{
return Instant.parse(strTime).toEpochMilli();
}
/**
* parse the offset times. example: 2015-11-10T16:43:29-0500 and 2014-05-14T17:29:23+00:00
*/
public static long parseOffsetTime(String strTime)
{
return OffsetDateTime.parse(strTime).toInstant().toEpochMilli();
}
,
java.time
java.util
的日期时间 API 及其格式化 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API。
- 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7。
- 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。
使用现代日期时间 API:
由于您的日期时间字符串符合 ISO-8601 格式,您可以直接(即不使用 DateTimeFormatter
)将其解析为 OffsetDateTime
。
import java.time.OffsetDateTime;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
String strDateTime = "2020-12-16T16:27:57+00:00";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
System.out.println(odt);
System.out.println("No of milliseconds from Epoch: " + odt.toInstant().toEpochMilli());
// Alternatively
System.out.println("No of milliseconds from Epoch: " + TimeUnit.SECONDS.toMillis(odt.toEpochSecond()));
}
}
输出:
2020-12-16T16:27:57Z
No of milliseconds from Epoch: 1608136077000
No of milliseconds from Epoch: 1608136077000
你的回答有什么问题?
-
使用
ZZ:ZZ
而不是单个X
:查看 documentation 以了解更多信息。另外,我不确定您是否将ZZ:ZZ
括在引号内,用于格式化代码,只是为了将其突出显示为代码,还是您真的在实际代码中这样做了。确保永远不要将Z
括在单引号内;否则,它只会将Z
表示为字符文字而不是时区。检查 this answer 以更好地理解它。 - 尽管此解析不是强制性的,但您不应在没有
SimpleDateFormat
的情况下使用DateTimeFormatter
或Locale
。检查 this answer 以更好地理解它。
使用旧 API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "2020-12-16T16:27:57+00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX",Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
System.out.println(date);
System.out.println("No of milliseconds from Epoch: " + date.getTime());
// Given below is how you can convert the legacy type,java.util.Date to the
// modern type java.time.Instant
Instant instant = date.toInstant();
System.out.println("No of milliseconds from Epoch: " + instant.toEpochMilli());
}
}
输出:
Wed Dec 16 16:27:57 GMT 2020
No of milliseconds from Epoch: 1608136077000
No of milliseconds from Epoch: 1608136077000
请注意,java.util.Date
对象不是像 modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1,1970,00:00:00 GMT
(或 UTC)。当您打印 java.util.Date
的对象时,它的 toString
方法返回 JVM 时区中的日期时间,从这个毫秒值计算出来。如果您需要在不同的时区打印日期时间,则需要将时区设置为 SimpleDateFormat
并从中获取格式化的字符串。