Java 如何将 UTC 日期/时间(字符串)解析为更具可读性的内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6543174/
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
How can I parse UTC date/time (String) into something more readable?
提问by LuxuryMode
I have a String of a date and time like this: 2011-04-15T20:08:18Z
. I don't know much about date/time formats, but I think, and correct me if I'm wrong, that's its UTC format.
我有一个日期和时间,像这样的字符串:2011-04-15T20:08:18Z
。我不太了解日期/时间格式,但我认为,如果我错了,请纠正我,这是它的 UTC 格式。
My question: what's the easiest way to parse this to a more normal format, in Java?
我的问题:在 Java 中将其解析为更正常格式的最简单方法是什么?
采纳答案by Andrew White
What you have is an ISO-8601date format which means you can just use SimpleDateFormat
您拥有的是ISO-8601日期格式,这意味着您可以只使用SimpleDateFormat
DateFormat m_ISO8601Local = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
And then you can just use SimpleDateFormat.parse(). Also, here is a blog postwith some examples that might help.
然后你可以只使用SimpleDateFormat.parse()。此外,这是一篇博客文章,其中包含一些可能会有所帮助的示例。
Update:
更新:
Read the comments below before using this solution.
在使用此解决方案之前,请阅读下面的评论。
回答by khmarbaise
You have to give the following format:
您必须提供以下格式:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date parse = simpleDateFormat.parse( "2011-04-15T20:08:18Z" );
回答by Joshua Pinter
Use JodaTime
使用JodaTime
I kept getting parsing errors using the other solutions with the Z
at the end of the format.
使用Z
格式末尾的其他解决方案时,我不断收到解析错误。
Instead, I opted to leverage JodaTime's excellent parsing functionality and was able to do the following very easily:
相反,我选择利用JodaTime出色的解析功能,并且能够非常轻松地执行以下操作:
String timestamp = "2011-04-15T20:08:18Z";
DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);
This correctly recognizes the UTC timezone and allows you to then use JodaTime's extensive manipulation methods to get what you want out of it.
这可以正确识别 UTC 时区,并允许您使用 JodaTime 的广泛操作方法来获取您想要的内容。
Hope this helps others.
希望这对其他人有帮助。
回答by jstricker
The Java 7 version of SimpleDateFormatsupports ISO-8601 time zones using the uppercase letter X
.
Java 7 版本的 SimpleDateFormat支持使用大写字母 的 ISO-8601 时区X
。
String string = "2011-04-15T20:08:18Z";
DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
Date date = iso8601.parse(string);
If you're stuck with Java 6 or earlier, the answer recommending JodaTime is a safe bet.
如果您坚持使用 Java 6 或更早版本,那么推荐 JodaTime 的答案是一个安全的选择。
回答by Basil Bourque
tl;dr
tl;博士
String output =
Instant.parse ( "2011-04-15T20:08:18Z" )
.atZone ( ZoneId.of ( "America/Montreal" ) )
.format (
DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL )
.withLocale ( Locale.CANADA_FRENCH )
)
;
vendredi 15 avril 2011 16 h 08 EDT
vendredi 2011 年 4 月 15 日美国东部时间 8 点 16 分
Details
细节
The answer by Josh Pinteris correct, but could be even simpler.
Josh Pinter的答案是正确的,但可能更简单。
java.time
时间
In Java 8 and later, the bundled java.util.Date/Calendar classes are supplanted by the java.time framework defined by JSR 310. Those classes are inspired by Joda-Timebut are entirely re-architected.
在 Java 8 及更高版本中,捆绑的 java.util.Date/Calendar 类被JSR 310定义的 java.time 框架所取代。这些类受到Joda-Time 的启发,但完全重新构建。
The java.time framework is the official successor to Joda-Time. The creators of Joda-Time have advised we should migrate to java.time as soon as is convenient. Joda-Time continues to be updated and tweaked, but further innovation will be done only in java.time and its extensions in the ThreeTen-Extraproject.
java.time 框架是 Joda-Time 的官方继承者。Joda-Time 的创建者建议我们应该尽快迁移到 java.time。Joda-Time 继续更新和调整,但进一步的创新将仅在 java.time 及其在ThreeTen-Extra项目中的扩展中完成。
The bulk of java.time functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backportproject, and further adapted to Android in ThreeTenABPproject.
大部分 java.time 功能已在ThreeTen- Backport项目中向后移植到 Java 6 和 7 ,并在ThreeTenABP项目中进一步适应 Android 。
The equivalent for the Joda-Time code above is quite similar. Concepts are similar. And like Joda-Time, the java.time classes by default use ISO 8601formats when parsing/generating textual representations of date-time values.
上面 Joda-Time 代码的等价物非常相似。概念是相似的。和 Joda-Time 一样,java.time 类在解析/生成日期时间值的文本表示时默认使用ISO 8601格式。
An Instant
is a moment on the timeline in UTCwith a resolution of nanoseconds(versus millisecondsused by Joda-Time & java.util.Date).
AnInstant
是UTC时间线上的一个时刻,分辨率为纳秒(与Joda-Time 和 java.util.Date 使用的毫秒相比)。
Instant instant = Instant.parse( "2011-04-15T20:08:18Z" );
Apply a time zone (ZoneId
) to get a ZonedDateTime
.
应用时区 ( ZoneId
) 以获取ZonedDateTime
.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Adjust into yet another time zone.
调整到另一个时区。
ZoneId zoneId_NewYork = ZoneId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt.withZoneSameInstant( zoneId_NewYork );
To create strings in other formats beyond those of the toString
methods, use the java.time.formatclasses. You can specify your own formatting pattern or let java.time localize automatically. Specify a Locale
for (a) the human language used in translation of name of month/day-of-week, and (b) cultural norms for period-versus-comma, order of the parts, and such.
要创建除这些toString
方法之外的其他格式的字符串,请使用java.time.format类。您可以指定自己的格式模式或让 java.time 自动本地化。指定 aLocale
用于 (a) 翻译月份/星期几名称时使用的人类语言,以及 (b) 句号与逗号、部分顺序等的文化规范。
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL );
formatter = formatter.withLocale( Locale.US );
String output = zdt_NewYork.format( formatter );
Friday, April 15, 2011 4:08:18 PM EDT
美国东部时间 2011 年 4 月 15 日星期五下午 4:08:18
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*
classes.
您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- java.time 类的更高版本的 Android 捆绑实现。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
Joda-Time
乔达时间
UPDATE:The Joda-Timeproject is now in maintenance mode, with the team advising migration to the java.timeclasses. This section left intact for history.
UPDATE:该乔达时间的项目现在处于维护模式,与团队的建议迁移java.time类。这部分为历史留下了完整的记录。
Pass String To Constructor
将字符串传递给构造函数
Joda-Timecan take that string directly. Simply pass to a constructor on the DateTimeclass.
Joda-Time可以直接使用该字符串。只需传递给DateTime类的构造函数。
Joda-Time understands the standard ISO 8601 formatof date-times, and uses that format as its default.
Joda-Time 理解日期时间的标准ISO 8601 格式,并使用该格式作为其默认格式。
Example Code
示例代码
Here is example code in Joda-Time 2.3 running in Java 7 on a Mac.
以下是在 Mac 上运行 Java 7 的 Joda-Time 2.3 中的示例代码。
I show how to pass the string to a DateTime constructor, in two ways: With and without a time zone. Specifying a time zone solves many problems people encounter in doing date-time work. If left unspecified, you get the default time zone which can bring surprises when placed into production.
我展示了如何将字符串传递给 DateTime 构造函数,有两种方式:带和不带时区。指定时区解决了人们在进行日期时间工作时遇到的许多问题。如果未指定,您将获得默认时区,这在投入生产时可能会带来惊喜。
I also show how specify no time zone offset (UTC/GMT) using the built-in constant DateTimeZone.UTC
. That's what the Z
on the end, short for Zulu
time, means: No time zone offset (00:00).
我还展示了如何使用内置常量指定无时区偏移 ( UTC/GMT) DateTimeZone.UTC
。这就是Z
最后(Zulu
时间的缩写)的意思:没有时区偏移(00:00)。
// ? 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// Default time zone.
DateTime dateTime = new DateTime( "2011-04-15T20:08:18Z" );
// Specified time zone.
DateTime dateTimeInKolkata = new DateTime( "2011-04-15T20:08:18Z", DateTimeZone.forID( "Asia/Kolkata" ) );
DateTime dateTimeInNewYork = new DateTime( "2011-04-15T20:08:18Z", DateTimeZone.forID( "America/New_York" ) );
// In UTC/GMT (no time zone offset).
DateTime dateTimeUtc = dateTimeInKolkata.toDateTime( DateTimeZone.UTC );
// Output in localized format.
DateTimeFormatter formatter = DateTimeFormat.shortDateTime().withLocale( Locale.US );
String output_US = formatter.print( dateTimeInNewYork );
Dump to console…
转储到控制台...
System.out.println("dateTime: " + dateTime );
System.out.println("dateTimeInKolkata: " + dateTimeInKolkata );
System.out.println("dateTimeInNewYork: " + dateTimeInNewYork );
System.out.println("dateTimeUtc: " + dateTimeUtc );
System.out.println("dateTime in US format: " + output_US );
When run…
运行时…
dateTime: 2011-04-15T13:08:18.000-07:00
dateTimeInKolkata: 2011-04-16T01:38:18.000+05:30
dateTimeInNewYork: 2011-04-15T16:08:18.000-04:00
dateTimeUtc: 2011-04-15T20:08:18.000Z
dateTime in US format: 4/15/11 4:08 PM
回答by Riccardo Casatta
I had a parse error in Andrew White solution. Adding the single quote around the Z solved the issue
我在 Andrew White 解决方案中遇到了解析错误。在 Z 周围添加单引号解决了这个问题
DateFormat m_ISO8601Local = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss'Z'");
回答by Mc Bton
For all the older versions of JDK (6 down) it may be useful.
对于所有旧版本的 JDK(6 下)它可能很有用。
Getting rid of trailing 'Z' and replacing it literally with 'UTC' timezone display name - then parsing the whole string using proper simple date formatter.
摆脱尾随 'Z' 并将其替换为 'UTC' 时区显示名称 - 然后使用适当的简单日期格式化程序解析整个字符串。
String timeZuluVal = "2011-04-15T20:08:18Z";
timeZuluVal = timeZuluVal.substring( 0, timeZuluVal.length() - 2 ); // strip 'Z';
timeZuluVal += " " + TimeZone.getTimeZone( "UTC" ).getDisplayName();
DateFormat simpleDateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss zzzz" );
Date dateVal = simpleDateFormat.parse( timeZuluVal );
回答by HelloImKevo
the pattern in @khmarbaise answer worked for me, here's the utility method I extracted (note that the Z is omitted from the pattern string):
@khmarbaise 答案中的模式对我有用,这是我提取的实用方法(注意模式字符串中省略了 Z):
/**
* Converts an ISO-8601 formatted UTC timestamp.
*
* @return The parsed {@link Date}, or null.
*/
@Nullable
public static Date fromIsoUtcString(String isoUtcString) {
DateFormat isoUtcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
isoUtcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
return isoUtcFormat.parse(isoUtcString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
回答by WitVault
Already has lot of answer but just wanted to update with java 8in case any one faced issues while parsing string date.
已经有很多答案,但只是想用java 8更新,以防有人在解析字符串日期时遇到问题。
Generally we face two problems with dates
通常我们会面临两个日期问题
- Parsing String to Date
- Display Date in desired string format
- 将字符串解析为日期
- 以所需的字符串格式显示日期
DateTimeFormatter
class in Java 8 can be used for both of these purpose.
Below methods try to provide solution to these issues.
DateTimeFormatter
Java 8 中的类可用于这两个目的。下面的方法试图为这些问题提供解决方案。
Method 1:Convert your UTC string to Instant. Using Instantyou can create Date for any time-zone by providing time-zone string and use DateTimeFormatter
to format date for display as you wish.
方法 1:将您的 UTC 字符串转换为Instant。使用Instant您可以通过提供时区字符串DateTimeFormatter
来为任何时区创建日期,并根据需要格式化日期以进行显示。
String dateString = "2016-07-13T18:08:50.118Z";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");
ZoneId zoneId = ZoneId.of(tz);
Instant instant = Instant.parse(dateString);
ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(dtf));
Method 2:
方法二:
Use DateTimeFormatter
built in constants e.g ISO_INSTANT
to parse string to LocalDate
.
ISO_INSTANT
can parse dates of pattern
使用DateTimeFormatter
内置常量,例如ISO_INSTANT
将字符串解析为LocalDate
.
ISO_INSTANT
可以解析模式的日期
yyyy-MM-dd'T'HH:mm:ssXe.g '2011-12-03T10:15:30Z'
yyyy-MM-dd'T'HH:mm:ssX例如'2011-12-03T10:15:30Z'
LocalDate parsedDate
= LocalDate.parse(dateString, DateTimeFormatter.ISO_INSTANT);
DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern("yyyy MM dd");
System.out.println(parsedDate.format(displayFormatter));
Method 3:
方法三:
If your date string has much precision of time e.g it captures fraction of seconds as well as in this case 2016-07-13T18:08:50.118Zthen method 1 will work but method 2 will not work. If you try to parse it will throw DateTimeException
Since ISO_INSTANT
formatter will not be able to parse fraction of seconds as you can see from its pattern.
In this case you will have to create a customDateTimeFormatter
by providing date pattern as below.
如果您的日期字符串具有很高的时间精度,例如它捕获几分之一秒以及在这种情况下2016-07-13T18:08:50.118Z那么方法 1 将起作用但方法 2 不起作用。如果您尝试解析它会抛出DateTimeException
因为ISO_INSTANT
格式化程序将无法解析秒的分数,正如您从其模式中看到的那样。在这种情况下,您必须通过提供如下日期模式来创建自定义DateTimeFormatter
。
LocalDate localDate
= LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX"));
Taken from a blog linkwritten by me.
摘自我写的博客链接。
回答by nAkhmedov
Joda Time
乔达时间
public static final String SERVER_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static DateTime getDateTimeFromUTC(String time) {
try {
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(SERVER_TIME_FORMAT).withZoneUTC();
Calendar localTime = Calendar.getInstance();
DateTimeZone currentTimeZone = DateTimeZone.forTimeZone(localTime.getTimeZone());
return dateTimeFormatter.parseDateTime(time).toDateTime().withZone(currentTimeZone);
} catch (Exception e) {
return DateTime.now();
}
}