如何使用 LocalDateTime 解析/格式化日期? (Java 8)
Java 8 添加了新的 java.time 用于处理日期和时间的 API (JSR 310)。
我将日期和时间作为字符串(例如,“2014-04-08 12:30”
)。如何获取 LocalDateTime
给定字符串的 实例?
在完成 LocalDateTime
对象的处理后:如何将 LocalDateTime
实例转换回与上面所示格式相同的字符串?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
解析日期和时间
从字符串中创建
localdatetime
对象您可以使用staticlocaldatetime.parse.parse()
方法。它采用一个字符串和datement formeformatter
作为参数。DateTimeFormatter
用于指定日期/时间模式。格式化日期和时间
要创建一个格式化的字符串
localDateTime
对象您可以使用form> format()
方法。请注意,在
dateTimeFormatter
中,有一些常用的日期/时间格式预定为常数。例如:使用dateTimeFormatter.iso_date_time
格式化localdateTime
实例从上方导致字符串“ 1986-04-04-08T12:30:00”
。parse()
和格式()
方法可用于所有日期/时间相关的对象(例如localdate
或zoneddateTime
)Parsing date and time
To create a
LocalDateTime
object from a string you can use the staticLocalDateTime.parse()
method. It takes a string and aDateTimeFormatter
as parameter. TheDateTimeFormatter
is used to specify the date/time pattern.Formatting date and time
To create a formatted string out a
LocalDateTime
object you can use theformat()
method.Note that there are some commonly used date/time formats predefined as constants in
DateTimeFormatter
. For example: UsingDateTimeFormatter.ISO_DATE_TIME
to format theLocalDateTime
instance from above would result in the string"1986-04-08T12:30:00"
.The
parse()
andformat()
methods are available for all date/time related objects (e.g.LocalDate
orZonedDateTime
)您也可以在
localdate.parse()
localdateTime.parse() string> String 上使用 localdate.parse() ,如果而无需提供模式> string
在。例如,
output ,
并仅当您必须处理其他日期模式时,使用
dateTimeFormatter
。例如,在下面的示例中, dd mmm uuuu 代表本月的一天(两个数字),三个月份的字母(2月,2月,3月, ,...)和四位数的年:
输出
还请记住,
dateTimeFormatter
对象是双向的;它既可以解析输入和格式输出。output
(请参阅完成格式化和解析dateformatter的模式列表)。
You can also use
LocalDate.parse()
orLocalDateTime.parse()
on aString
without providing it with a pattern, if theString
is in ISO 8601 format.For example,
Output,
And use
DateTimeFormatter
only if you have to deal with other date patterns.For instance, in the following example, dd MMM uuuu represents the day of the month (two digits), three letters of the name of the month (Jan, Feb, Mar,...), and a four-digit year:
Output
also remember that the
DateTimeFormatter
object is bidirectional; it can both parse input and format output.Output
(See complete list of Patterns for Formatting and Parsing DateFormatter.)
Sufiyan Ghori 和 <一href="https://stackoverflow.com/questions/22463062/how-can-i-parse-format-dates-with-localdatetime-java-8/22463063#22463063">micha的答案很好地解释了关于字符串模式的问题。但是,如果您使用 ISO 8601,则无需申请
DateTimeFormatter
因为 LocalDateTime 已经准备好了:将 LocalDateTime 转换为时区 ISO 8601 字符串
转换从 ISO8601 字符串返回 LocalDateTime
Both Sufiyan Ghori's and micha's answer explain very well the question regarding string patterns. However, just in case you are working with ISO 8601, there isn't any need to apply
DateTimeFormatter
since LocalDateTime is already prepared for it:Convert a LocalDateTime to a Time Zone ISO 8601 String
Convert from ISO8601 String back to a LocalDateTime
用日期和时间在特定时间点中解析字符串(Java称其为“
即时
”)非常复杂。 Java在几次迭代中一直在解决这个问题。最新的一个,java.time
和java.time.chrono
,涵盖了几乎所有需求(时间扩张 :))。但是,这种复杂性带来了很多混乱。
理解日期解析的关键是:
为什么Java有这么多方法来解析日期?
幸运的是,整个(商业)世界设法使用了相同的使用。
。...为什么
localdatetime
,ZonedDateTime
等。如此复杂的有时区。
时区基本上是地球表面的“条纹”* [3] ,其当局遵循相同的规则,即何时有时间偏移。这包括夏季规则。
时区随着时间的流逝而变化,主要是基于谁征服了谁。和一个时区的规则随着时间的流逝而更改。
有时间偏移。这与时区不同,因为时区可能是,例如“布拉格”,但是夏季时间偏移和冬季偏移。
如果您获得了时区的时间戳,则偏移可能会有所不同,具体取决于一年中的哪一部分。在leap时,时间戳可能意味着两个不同的时间,因此没有其他信息,它可以' t可靠地转换。
注意:由 timestamp 我的意思是“一个包含日期和/或时间的字符串,可选地使用时区和/或时间偏移。”
几个时区可以共享某些时期的同一时间偏移。例如,GMT/UTC时区与夏季时间偏移无效的“伦敦”时区相同。
使其更加复杂(但这对您的用例并不重要):
科学家观察到地球的动态,随着时间的流逝而变化;基于这一点,他们在个体年代结束时增加了几秒钟。 (So 2040-12-31 24:00:00 可能是有效的日期时间。)这需要对系统用来正确具有日期转换的元数据的定期更新。例如,在Linux上,您会定期更新Java软件包,包括这些新数据。
更新并不总是保留历史和未来时间戳的先前行为。因此,可能会发生在某个时区的更改周围的两个时间戳进行分析,以比较它们可能会给出不同的结果。这也适用于受影响时区和其他时区之间的比较。
是否应该在您的软件中引起错误,请考虑使用某些没有复杂规则的时间戳,例如 Unix Timestamp 。
由于有7个,对于未来的日期,我们无法确切地转换日期。因此,例如, 8524-02-17的当前解析12:00:00 可能会从未来解析的几秒钟内退出。
JDK的API随着当代的需求而发展,
java.util.date
,它具有有点幼稚的方法,假设只是一年,月,一天,时间和时间。这很快就不够了。日历
API。如何在Java的
Java.Time
中处理它,解析时间戳的类型
确定要在消费时间戳字符串时 ,您需要知道它包含哪些信息。 这是关键点。如果您不正确,最终会得到一个隐秘的例外,例如“无法创建瞬间”,“ Zone Offset Misssist”,“ Unknown Zone ID”,等等
< >它包含日期和时间吗?
是否有时间偏移?
时间偏移是+hh:mm 零件。有时,+00:00 可以用 z 作为'zulu time',
utc
作为通用时间协调,或 gmt < /em>作为格林威治的平均时间。这些也设定了时区。对于这些时间戳,您可以使用
offsetDateTime
。
它有时区吗?
对于这些时间戳,您可以使用 noreferrer“ > 。
区域是由
指定的
时区列表由a “ noreferrer”>“ noreferrer”>“ tz database” ,由 icaan 。
根据
ZoneID
的Javadoc,可以以某种方式将区域ID指定为 Z 和Offset。我不确定这是如何映射到真实区域的。如果只有TZ的时间戳属于一个时间偏移的时间偏移更改,那么它是模棱两可的,解释是
resolverstyle
的主题,请参见下文。。
如果它没有,则假定或忽略了缺失的上下文。消费者必须决定。因此,它需要以
localDateTime
进行解析,并通过添加丢失的信息来转换为offsetDateTime
:部分时间信息
localdate
,localtime
,offsetTime
,月日
,<代码>年,或YearMonth
。如果您有完整的信息,则可以获得
java.time.instant
。这也用于内部用于在OffSetDateTime
和ZonedDateTime
之间转换。弄清楚如何解析它,
DateTimeFormatter
可以将时间戳字符串和格式解析为字符串。代码> DateTimeFormatter s 应涵盖或多或少涵盖所有标准时间戳格式。例如,
iso_instant
可以解析2011-12-03T10:15:30.123457Z
。如果您有一些特殊的格式,则可以创建自己的dateTimeFormatter (这也是解析器) 。
我建议查看
dateTimeFormatter
的源代码,并在如何使用dateTimeFormatterBuilder
上构建一个源代码。当您在那里时,还要查看Resolverstyle
,它控制解析器是宽大,智能还是严格的格式和模棱两可的信息。现在, YeaterAlaccessor
,经常出现的错误是进入
terumalaccessor
的复杂性。这来自开发人员使用simpledateformatter.parse(string)
的方式。对,datementingformatter.parse(“ ...”)
给您temeralAccessor
。但是,通过上一节的知识,您可以方便地分解为所需的类型:
您实际上也不需要
dateTimeFormatter
。您要解析的类型具有Parse(String)
方法。关于
terunalAccessor
,如果您对字符串中有哪些信息有模糊的了解,并且想在运行时做出决定,则可以使用它。我希望我对您的灵魂有所了解:)
注意:
java.time
的后退到Java 6和7: threeten-backport 。对于Android,它具有 threetenabp 。[3] 不仅是它们不是条纹,而且还有一些奇怪的极端。例如,一些邻近的太平洋岛屿和-11:00时区。这意味着,在一个岛上,在5月3日下午1日,在另一个岛屿上,它仍然是4月30日下午30点(如果我正确计数的话:))
Parsing a string with date and time into a particular point in time (Java calls it an "
Instant
") is quite complicated. Java has been tackling this in several iterations. The latest one,java.time
andjava.time.chrono
, covers almost all needs (except time dilation :) ).However, that complexity brings a lot of confusion.
The key to understand date parsing is:
Why does Java have so many ways to parse a date?
Fortunately, the whole (business) world managed to use the same.
...and why is the
LocalDateTime
,ZonedDateTime
et al. so complicatedThere are time zones.
A time zone is basically a "stripe"*[3] of the Earth's surface whose authorities follow the same rules of when does it have which time offset. This includes summer time rules.
The time zones change over time for various areas, mostly based on who conquers whom. And one time zone's rules change over time as well.
There are time offsets. That is not the same as time zones, because a time zone may be, e.g., "Prague", but that has summer time offset and winter time offset.
If you get a timestamp with a time zone, the offset may vary, depending on what part of the year it is in. During the leap hour, the timestamp may mean two different times, so without additional information, it can't be reliably converted.
Note: By timestamp I mean "a string that contains a date and/or time, optionally with a time zone and/or time offset."
Several time zones may share the same time offset for certain periods. For instance, the GMT/UTC time zone is the same as the "London" time zone when the summer time offset is not in effect.
To make it a bit more complicated (but that's not too important for your use case):
The scientists observe Earth's dynamic, which changes over time; based on that, they add seconds at the end of individual years. (So 2040-12-31 24:00:00 may be a valid date-time.) This needs regular updates of the metadata that systems use to have the date conversions right. E.g., on Linux, you get regular updates to the Java packages including these new data.
The updates do not always keep the previous behavior for both historical and future timestamps. So it may happen that parsing of the two timestamps around some time zone's change comparing them may give different results when running on different versions of the software. That also applies to comparing between the affected time zone and other time zone.
Should this cause a bug in your software, consider using some timestamp that does not have such complicated rules, like Unix timestamp.
Because of 7, for the future dates, we can't convert dates exactly with certainty. So, for instance, current parsing of 8524-02-17 12:00:00 may be off a couple of seconds from the future parsing.
JDK's APIs for this evolved with the contemporary needs
java.util.Date
which had a bit naive approach, assuming that there's just the year, month, day, and time. This quickly did not suffice.java.sql.Date
was introduced, with its own limitations.Calendar
API was introduced.How to deal with it in Java's
java.time
Determine what type to parse a timestamp to
When you are consuming a timestamp string, you need to know what information it contains. This is the crucial point. If you don't get this right, you end up with a cryptic exceptions like "Can't create Instant", "Zone offset missing", "unknown zone id", etc.
Does it contain the date and the time?
Does it have a time offset?
A time offset is the +hh:mm part. Sometimes, +00:00 may be substituted with Z as 'Zulu time',
UTC
as Universal Time Coordinated, or GMT as Greenwich Mean Time. These also set the time zone.For these timestamps, you use
OffsetDateTime
.Does it have a time zone?
For these timestamps, you use
ZonedDateTime
.Zone is specified either by
The list of time zones is compiled by a "TZ database", backed by ICAAN.
According to
ZoneId
's javadoc, the zone id's can also somehow be specified as Z and offset. I'm not sure how this maps to real zones.If the timestamp, which only has a TZ, falls into a leap hour of time offset change, then it is ambiguous, and the interpretation is subject of
ResolverStyle
, see below.If it has neither, then the missing context is assumed or neglected. And the consumer has to decide. So it needs to be parsed as
LocalDateTime
and converted toOffsetDateTime
by adding the missing info:Duration
), or when you don't know and it doesn't really matter (e.g., local bus schedule).Partial time information
LocalDate
,LocalTime
,OffsetTime
,MonthDay
,Year
, orYearMonth
out of it.If you have the full information, you can get a
java.time.Instant
. This is also internally used to convert betweenOffsetDateTime
andZonedDateTime
.Figure out how to parse it
There is an extensive documentation on
DateTimeFormatter
which can both parse a timestamp string and format to string.The pre-created
DateTimeFormatter
s should cover more or less all standard timestamp formats. For instance,ISO_INSTANT
can parse2011-12-03T10:15:30.123457Z
.If you have some special format, then you can create your own DateTimeFormatter (which is also a parser).
I recommend to look at the source code of
DateTimeFormatter
and get inspired on how to build one usingDateTimeFormatterBuilder
. While you're there, also have a look atResolverStyle
which controls whether the parser is LENIENT, SMART or STRICT for the formats and ambiguous information.TemporalAccessor
Now, the frequent mistake is to go into the complexity of
TemporalAccessor
. This comes from how the developers were used to work withSimpleDateFormatter.parse(String)
. Right,DateTimeFormatter.parse("...")
gives youTemporalAccessor
.But, equipped with the knowledge from the previous section, you can conveniently parse into the type you need:
You do not actually need to the
DateTimeFormatter
either. The types you want to parse have theparse(String)
methods.Regarding
TemporalAccessor
, you can use it if you have a vague idea of what information there is in the string, and want to decide at runtime.I hope I shed some light of understanding onto your soul :)
Note: There's a backport of
java.time
to Java 6 and 7: ThreeTen-Backport. For Android it has ThreeTenABP.[3] Not just that they are not stripes, but there also some weird extremes. For instance, some neighboring Pacific Islands have +14:00 and -11:00 time zones. That means, that while on one island, there is 1st May 3 PM, on another island not so far, it is still 30 April 12 PM (if I counted correctly :) )
使用
LocalDateTime.Parse
要注意的另一件事是,您不能将其与仅具有date formatter字符的自定义格式化器一起使用,例如uuuuumdd
。在这种情况下,您应该改用localdate.parse
。例如:Another thing to note with
LocalDateTime.parse
is that you cannot use it with a custom formatter with only date formatter characters, such asuuuuMMdd
. In this case, you should useLocalDate.parse
instead. For example:以所需格式获取当前 UTC 时间
Get the current UTC time in the required format
所有的答案都很好。 Java 8+ 版本具有以下用于解析和格式化时区的模式:
V
、z
、O
、X
,x
,Z
。这是根据文档中的规则进行解析的:
但是格式化怎么样?
下面是一个日期示例(假设
ZonedDateTime
),它显示了不同格式模式的这些模式行为:在正偏移量的情况下,
+
符号字符随处使用(其中现在有-
)并且从未省略。这对于新的
java.time
类型非常有效。如果您打算将它们用于 java.util.Date 或 java.util.Calendar - 并非所有类型都可以工作,因为这些类型已损坏(因此标记为已弃用,请不要使用它们)。All the answers are good. The Java 8+ versions have these patterns for parsing and formatting time zones:
V
,z
,O
,X
,x
,Z
.Here's they are, for parsing, according to rules from the documentation:
But how about formatting?
Here's a sample for a date (assuming
ZonedDateTime
) that show these patters behavior for different formatting patters:In the case of positive offset, the
+
sign character is used everywhere (where there is-
now) and never omitted.This well works for new
java.time
types. If you're about to use these forjava.util.Date
orjava.util.Calendar
- not all going to work as those types are broken (and so marked as deprecated, please don't use them).通用方法如下所示。它适用于:
yyyy-MM-dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss.S
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm
yyyy-MM-dd HH
yyyy-MM-dd
The universal method looks as below. It works for:
yyyy-MM-dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss.S
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm
yyyy-MM-dd HH
yyyy-MM-dd
让我们提取两个问题,示例字符串
“ 2014-04-08 12:30”
DT
应该允许您进行所有与日期相关的操作Let's take two questions, example string
"2014-04-08 12:30"
dt
should allow you to all date-time related operations这个问题已经有很多好的答案。此答案显示了如何使用预定义
dateTimeFormatter
s构建dateTimeFormatter
,该可以解析给定的日期时间字符串。但是,使用此
dateTimeFormatter
将获得的LocalDateTime
格式化将在hh:mm:mm:ss
格式中返回字符串。要将时间字符串限制为HH:MM
格式,我们仍然必须使用模式uuuuu-mm-dd hh:mm
,就像其他答案所做的那样。demo :
输出:
在线demo < < /a>
注意:在这里,您可以使用
y
而不是u
,但我更喜欢u
而不是y
。从 trail> trail> trail:日期时间< /a> 。
There are already many good answers to this question. This answer shows how to use predefined
DateTimeFormatter
s to build aDateTimeFormatter
which can parse the given date-time string.However, formatting the obtained
LocalDateTime
using thisDateTimeFormatter
will return a string with time inHH:mm:ss
format. To restrict the time string toHH:mm
format, we still have to use the patternuuuu-MM-dd HH:mm
as other answers have done.Demo:
Output:
ONLINE DEMO
Note: Here, you can use
y
instead ofu
but I preferu
toy
.Learn more about the modern Date-Time API from Trail: Date Time.
我发现涵盖这样的日期时间格式的多种变体非常好:
I found it wonderful to cover multiple variants of date time formats like this:
当我有一个类型
java.time.localdatetime
的变量时,以获得理想格式的日期,我不想使用中间类-27 11:17
您可以调整“子字符串”中的值以检索所需的内容。
我想指出的是,这在每种情况下都不是合适的方法。
When I have a variable of type
java.time.LocalDateTime
to get the date with a desirable format and I don't want to use intermediate classes, I just do:The value of nowDateInString : 2023-10-27 11:17
You can adjust the value in 'substring' to retrieve what you want.
I would like to point out that this is not a suitable method in every situation.