[英]Removing nanoseconds in a datetime string
I have dates in potentially 2 formats: 我有可能有2种格式的日期:
2013-07-03T14:30:38Z
2013-07-03T14:30:38.000000Z
I want to axe the .00000
if it exists 如果它存在,我想要.00000
I got this far, to remove everything after the '.' 我到目前为止,删除'。'后的所有内容。 time.replaceFirst( "^(.*?)\\\\b\\\\..*$"
, "$1"); time.replaceFirst( "^(.*?)\\\\b\\\\..*$"
,“$ 1”);
result: 2013-07-03T14:30:38
结果: 2013-07-03T14:30:38
Problem is, I still need the ' Z
' .. how can I keep the Z
? 问题是,我仍然需要' Z
'..我怎么能保持Z
?
so I'm not entirely sure if there will always be 6 0s (if the string contains the nanoseconds) or if there can be a variable number of 0s... 所以我不完全确定是否总会有6 0(如果字符串包含纳秒)或者是否可以有0的可变数量...
I'm using java but didn't want to tag it as java since it's basically just pure regex 我正在使用java但不想将其标记为java,因为它基本上只是纯正则表达式
Simply add the Z
back inside: 只需将Z
添加回内部:
time.replaceFirst( "^(.*?)\\b\\..*$", "$1Z");
And alternative would be to capture everything until you encounter the period character ( .
): 另一种方法是捕获所有内容,直到遇到句点字符( .
):
time.replaceFirst( "^([^.]+).*(Z)$", "$1$2");
I should correct the terminology in the Question: You (apparently) have strings in a certain format, not "dates". 我应该更正问题中的术语:你(显然)有某种格式的字符串 ,而不是“日期”。 Do not confuse date-time values with their String representations. 不要将日期时间值与其字符串表示混淆。
Just as "$12.34" is not a number, it is a string representation of a number with a certain format applied. 正如“$ 12.34”不是数字一样,它是应用了某种格式的数字的字符串表示。 That string can be parsed into a number. 该字符串可以解析为数字。
This concept is the essence of the following code. 这个概念是以下代码的本质。 We parse a string to instantiate a date-time object, then use that date-time object to generate a new string representation. 我们解析一个字符串来实例化一个日期时间对象,然后使用该日期时间对象生成一个新的字符串表示。
Java 8 and later has a new java.time framework built-in ( Tutorial ). Java 8及更高版本内置了一个新的java.time框架 ( Tutorial )。 You could use that for parsing a string as a date-time value, and then generating a new string representation in any format you desire. 您可以使用它将字符串解析为日期时间值,然后以您希望的任何格式生成新的字符串表示形式。 Here's some code if you want to explore this as an alternative to regex. 如果你想探索这个作为正则表达式的替代品,这里有一些代码。
Both of your possible formats are nearly in ISO 8601 format. 两种可能的格式都接近ISO 8601格式。 Strictly speaking the standard expects only millisecond resolution (3 decimal places) as far as I know, but the java.time framework extends that to nanosecond (up to 9 decimal places). 严格来说,就我所知,标准只需要毫秒级的分辨率(3位小数),但java.time框架将其扩展到纳秒 (最多9位小数)。
The java.time framework uses ISO 8601 as its default when parsing and generating strings. 解析和生成字符串时,java.time框架使用ISO 8601作为其默认值。 So you need not specify a formatter pattern, and instead can use one of the several predefined formatters aimed at ISO 8601 standard formats. 因此,您无需指定格式化程序模式,而是可以使用针对ISO 8601标准格式的多个预定义格式化程序之一。
An Instant
object represents a moment on the timeline in UTC . Instant
对象表示UTC时间轴上的时刻。 You could assign a particular time zone to get a ZonedDateTime
, but not needed for this particular Question. 您可以指定特定时区来获取ZonedDateTime
,但此特定问题不需要。 This class can parse your input strings by default. 默认情况下,此类可以解析输入字符串。
String input = "2013-07-03T14:30:38.123456789Z";
Instant instant = Instant.parse( input );
After parsing we have an instant
object in hand. 解析后,我们手头有一个instant
对象。 From there we can effectively truncate the fractions of a second by calling the with
method to change the fractional second to zero. 从那里我们可以通过调用with
方法将小数秒更改为零来有效地截断一秒的分数。 Technically speaking we are not changing the fractional seconds, as java.time uses immutable objects . 从技术上讲,我们不会改变小数秒,因为java.time使用不可变对象 。 A new object is created based on the values of the original. 基于原始值创建新对象。
Instant instantTruncated = instant.with( ChronoField.NANO_OF_SECOND , 0 );
Lastly we use the predefined formatter, DateTimeFormatter.ISO_INSTANT
. 最后,我们使用预定义的格式化程序DateTimeFormatter.ISO_INSTANT
。 This formatter automatically suppresses the fractional zero from the generated string in groups of three digits where the value is zero. 此格式化程序会自动抑制生成的字符串中的小数零,其中三位数的值为零。 So …7.12
prints as …7.120
, …7.1234
as …7.123400
, and …7.0
as …7
. 所以…7.12
打印为…7.120
, …7.1234
为…7.123400
, …7.0
为…7
。 That last value is fits our needs. 最后一个值符合我们的需求。
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
String output = formatter.format( instantTruncated );
The toString
method on Instant
uses the formatter DateTimeFormatter.ISO_INSTANT
by default. Instant
上的toString
方法默认使用格式化程序DateTimeFormatter.ISO_INSTANT
。 So technically we could shorten the code to just call toString
. 所以从技术上讲,我们可以缩短代码来调用toString
。 But I want to show explicitly how a formatter is involved. 但我想明确地说明格式化程序是如何涉及的。
Dump to console. 转储到控制台。
System.out.println( "instant: " + instant );
System.out.println( "instantTruncated: " + instantTruncated );
System.out.println( "output: " + output );
When run. 跑步时
instant: 2013-07-03T14:30:38.123456789Z
instantTruncated: 2013-07-03T14:30:38Z
output: 2013-07-03T14:30:38Z
We can assign a time zone to that Instant to get a 'ZonedDateTime`. 我们可以为该Instant分配一个时区来获得'ZonedDateTime`。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instantTuncated , zoneId);
I'm using java but didn't want to tag it as java since it's basically just pure regex 我正在使用java但不想将其标记为java,因为它基本上只是纯正则表达式
It's probably best to approach with java.time
, 最好接近java.time
,
but since you insist: 但既然你坚持:
time.replaceFirst( "\\.\\d*(Z)?$", "$1");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.