Java 将时间字符串转换为 ISO 8601 格式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32163678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting a time String to ISO 8601 format
提问by CodeMonkey
I am trying to create a String in a format like 2015-08-20T08:26:21.000Z
to 2015-08-20T08:26:21Z
我正在尝试以2015-08-20T08:26:21.000Z
到2015-08-20T08:26:21Z等格式创建字符串
I know it can be done with some String splitting techniques, but i am wondering if there is an elegant solution for that (with minimal code changes).
我知道它可以通过一些字符串拆分技术来完成,但我想知道是否有一个优雅的解决方案(代码更改最少)。
Both of the above are time strings, the final one which i need is Date in ISO 8601 . http://tools.ietf.org/html/rfc3339#section-5.6
以上都是时间字符串,我需要的最后一个是 ISO 8601 中的 Date 。http://tools.ietf.org/html/rfc3339#section-5.6
I have tried a few similar questions like converting a date string into milliseconds in javabut they dont actually solve the purpose.
我尝试了一些类似的问题,比如在 java 中将日期字符串转换为毫秒,但它们实际上并没有解决目的。
Also tried using :
还尝试使用:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
But it still does not do any String to String conversions. Getting the following error:
但它仍然不进行任何字符串到字符串的转换。得到以下错误:
23:04:13,829 WARN [RuntimeExceptionMapper] caught RuntimeException: {}: java.lang.IllegalArgumentException: Cannot format given Object as a Date
23:04:13,829 警告 [RuntimeExceptionMapper] 捕获了运行时异常:{}:java.lang.IllegalArgumentException:无法将给定的对象格式化为日期
Is there some library which someone can suggest ?
有人可以推荐一些图书馆吗?
Thanks.
谢谢。
采纳答案by Basil Bourque
tl;dr
tl;博士
Instant.parse( "2015-08-20T08:26:21.000Z" )
.toString()
2015-08-20T08:26:21Z
2015-08-20T08:26:21Z
Date-Time Formatter
日期时间格式化程序
If all you want to do is eliminate the .000
, then use date-time objects to parse your input string value, then generate a new string representation of that date-time value in a different format.
如果您只想消除.000
,然后使用日期时间对象来解析您的输入字符串值,然后以不同格式生成该日期时间值的新字符串表示形式。
ISO 8601
ISO 8601
By the way, if that is your goal, the Question's title make no sense as both strings mentioned in the first sentence are valid ISO 8601formatted strings.
顺便说一句,如果这是您的目标,那么问题的标题没有意义,因为第一句中提到的两个字符串都是有效的ISO 8601格式字符串。
2015-08-20T08:26:21.000Z
2015-08-20T08:26:21Z
2015-08-20T08:26:21.000Z
2015-08-20T08:26:21Z
java.time
时间
Java 8 and later has the new java.time package. These new classes supplant the old java.util.Date/.Calendar & java.text.SimpleDateFormat classes. Those old classes were confusing, troublesome, and flawed.
Java 8 及更高版本具有新的java.time 包。这些新类取代了旧的 java.util.Date/.Calendar 和 java.text.SimpleDateFormat 类。那些旧的课程很混乱,很麻烦,而且有缺陷。
Instant
立即的
If all you want is UTC time zone, then you can use the Instant
class. This class represents a point along the timeline without regard to any particular time zone (basically UTC).
如果您只想要 UTC 时区,那么您可以使用Instant
该类。此类代表时间线上的一个点,不考虑任何特定时区(基本上是 UTC)。
DateTimeFormatter.ISO_INSTANT
DateTimeFormatter.ISO_INSTANT
Calling an Instant's toString
generates a String representation of the date-time value using a DateTimeFormatter.ISO_INSTANT
formatter instance. This formatter is automatically flexible about the fractional second. If the value has a whole second, no decimal places are generated (apparently what the Question wants). For a fractional second, digits appear in groups of 3, 6, or 9, as needed to represent the value up to nanosecond resolution. Note: this format may exceed ISO 8601 limit of milliseconds (3 decimal places).
调用 Instant 会toString
使用DateTimeFormatter.ISO_INSTANT
格式化程序实例生成日期时间值的字符串表示形式。此格式化程序在小数秒内自动灵活。如果该值有一整秒,则不会生成小数位(显然是问题想要的)。对于小数秒,数字以 3、6 或 9 为一组出现,以表示高达纳秒分辨率的值。注意:此格式可能会超出 ISO 8601 毫秒限制(3 个小数位)。
Example code
示例代码
Here is some example code in Java 8 Update 51.
这是 Java 8 Update 51 中的一些示例代码。
String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );
output: 2015-08-20T08:26:21Z
输出:2015-08-20T08:26:21Z
Changing to a fractional second, .08
更改为小数秒, .08
String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );
output: 2015-08-20T08:26:21.080Z
输出:2015-08-20T08:26:21.080Z
If interested in any time zone other than UTC, then make a ZonedDateTime
object from that Instant
.
如果对 UTC 以外的任何时区感兴趣,那么ZonedDateTime
从那个Instant
.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;
回答by karim mohsen
Your format is just not right try this :-
你的格式不正确试试这个:-
try {
String s = "2015-08-20T08:26:21.000Z";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date d = df.parse(s);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
System.out.println(sdf.format(d));
} catch (ParseException e) {
e.printStackTrace();
}
回答by Emily Mabrey
Conversion of a date String
of unknown formatting into a date String
that uses known formatting can be accomplished using two DateFormat
objects- one dynamically configured to parse the format of the input String
, and one configured to generate the formatted output String
. For your situation the input String
formatting is unspecified and must be provided by the caller, however, the output String
formatting can be configured to use ISO 8601 formatting without additional input. Essentially, generating an ISO 8601 formatted date String
output requires two inputs provided by the caller- a String
containing the formatted date and another String
that contains the SimpleDateFormat
format.
可以使用两个对象String
将未知格式的日期转换为String
使用已知格式的日期DateFormat
- 一个动态配置为解析输入格式String
,另一个配置为生成格式化输出String
。对于您的情况,输入String
格式未指定并且必须由调用者提供,但是,输出String
格式可以配置为使用 ISO 8601 格式而无需额外输入。本质上,生成 ISO 8601 格式化日期String
输出需要调用者提供的两个输入——一个String
包含格式化日期,另一个String
包含SimpleDateFormat
格式。
Here is the described conversion as Java code (I deliberately have left out null checks and validations, add these as appropriate for your code):
这是作为 Java 代码描述的转换(我故意省略了空检查和验证,根据您的代码添加这些):
private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {
final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
final Date inputDate = inputDateFormatter.parse(inputDateAsString);
return iso8601DateFormatter.format(inputDate);
}
If you want to modify that method please note that SimpleDateFormat
is not thread-safe, and that you should not use it from a static context without a workaround for multi-threaded code (ThreadLocal
is commonly used to do just such a workaround for SimpleDateFormat
).
如果您想修改该方法,请注意它SimpleDateFormat
不是线程安全的,并且您不应在没有多线程代码变通方法的情况下从静态上下文中使用它(ThreadLocal
通常用于为 做这样的变通方法SimpleDateFormat
)。
An additional "gotcha" is the use of a Locale
during the construction of the SimpleDateFormat
objects- do not remove the Locale
configuration. It is not safe to allow the system to choose to use the default Locale
because that is user/machine specific. If you do allow it to use the default Locale
, you run the risk of transient bugs because your development machine uses a Locale
different than the Locale
of your end-user. You do not have to use my selected ENGLISH Locale
, it is perfectly fine to use a different Locale (you should understand the rules of that Locale
and modify the code as appropriate however). Specification of no Locale
and utilization of the system default is incorrect however, and likely will lead to many frustrating hours trying to diagnose an elusive bug.
一个额外的“陷阱”是Locale
在构建对象期间使用 a SimpleDateFormat
- 不要删除Locale
配置。允许系统选择使用默认值是不安全的,Locale
因为这是特定于用户/机器的。如果您确实允许它使用默认Locale
,则您将面临暂时性错误的风险,因为您的开发机器使用Locale
的Locale
与您的最终用户不同。您不必使用我选择的 ENGLISH Locale
,使用不同的 Locale 完全没问题(您应该了解其中的规则Locale
并根据需要修改代码)。Locale
然而,系统默认值的 no和利用率的规范是不正确的,并且可能会导致许多令人沮丧的时间试图诊断一个难以捉摸的错误。
Please understand this solution is not ideal as of Java 8 and the inclusion of the JodaTime based classes, like Instant
. I chose to answer using the outdated API's because those were what you seemed concerned with in your question. If you are using Java 8 I strongly urge to learn and utilize the new classes as they are an improvement in almost every conceivable way.
请理解此解决方案在 Java 8 中并不理想,并且包含基于 JodaTime 的类,例如Instant
. 我选择使用过时的 API 来回答,因为这些是您在问题中似乎关心的。如果您使用的是 Java 8,我强烈建议您学习和利用新类,因为它们几乎在所有可以想到的方面都有所改进。