[英]How to parse UTC timestamp of format yyyy-MM-ddTHH:mm:ss.SSS+ZZZZ
I have timestamp as 2020-12-03T05:35:59.398+0000
in String
format being recieved in a streaming batch.我的时间戳为
2020-12-03T05:35:59.398+0000
在流式批处理中收到的String
格式。
I want only 2020-12-03 05:35:59
as java.sql.Timestamp
instance in order to be able to compare it with other Timestamp
instance.我只想要
2020-12-03 05:35:59
作为java.sql.Timestamp
实例,以便能够将其与其他Timestamp
实例进行比较。
Getting following error with Timestamp.valueOf()
function: Timestamp.valueOf()
function 出现以下错误:
Exception in thread "main" java.time.format.DateTimeParseException : Text '2020-12-03T05:35:59.398+0000' could not be parsed at index 23
I tried the answer given here , and conversion did happen but the time was changed to 2020-12-03 11:05:59
我尝试了这里给出的答案,并且确实发生了转换,但时间更改为
2020-12-03 11:05:59
I have tried changing between the formats given here but still no solution.我尝试在此处给出的格式之间进行更改,但仍然没有解决方案。
Is there even a format for timestamp with wierd +
in between 398+0000
?甚至在
398+0000
之间有带有奇怪+
的时间戳格式吗?
I recommend that you use java.time, the modern Java date and time API, for your date and time work.我建议您使用 java.time,现代 Java 日期和时间 API,用于您的日期和时间工作。
DateTimeFormatter isoFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxx");
DateTimeFormatter sqlTimestampFormatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
String aTimestampString = "2020-12-03T05:35:59.398+0000";
String anotherTimestampString = "2020-12-04 06:43:58.556385";
Instant anInstant = isoFormatter.parse(aTimestampString, Instant::from);
Instant anotherInstant = LocalDateTime.parse(anotherTimestampString, sqlTimestampFormatter)
.atOffset(ZoneOffset.UTC)
.toInstant();
if (anInstant.isBefore(anotherInstant)) {
System.out.println(aTimestampString + " is earlier");
} else {
System.out.println(anotherTimestampString + " is earlier");
}
Output from this example is:此示例中的 Output 是:
2020-12-03T05:35:59.398+0000 is earlier
2020-12-03T05:35:59.398+0000 更早
The +0000
in the former string above is an offset from UTC — an offset of 00 hours 00 minutes.上面前一个字符串中的
+0000
是与 UTC 的偏移量 - 00 小时 00 分钟的偏移量。 Since it is zero, we know that the time is in UTC.由于它为零,我们知道时间是 UTC。 I don't know the time zone or UTC offset of the other string.
我不知道另一个字符串的时区或 UTC 偏移量。 You need to know, or you will get incorrect results.
你需要知道,否则你会得到不正确的结果。 In the code above I have assumed that the other string is in UTC too.
在上面的代码中,我假设另一个字符串也是 UTC。
I tried the answer given here, and conversion did happen but the time was changed to
2020-12-03 11:05:59
我尝试了这里给出的答案,确实发生了转换,但时间改为
2020-12-03 11:05:59
This is how confusing the Timestamp
class is.这就是
Timestamp
class 的混乱程度。 You got the correct timestamp value.你得到了正确的时间戳值。 What happens when you print the
Timestamp
object, is that you are (implicitly or explicitly) calling its toString
method.当您打印
Timestamp
object 时会发生什么,是您(隐式或显式)调用其toString
方法。 Timestamp.toString()
confusingly uses the default time zone of your JVM for rendering the string. Timestamp.toString()
混淆使用 JVM 的默认时区来呈现字符串。 So if your timestamp is equal to 2020-12-03T05:35:59.398 UTC and your time zone is, say, Asia/Kolkata, then time is converted to Asia/Kolkata time zone and the string 2020-12-03 11:05:59
is returned and printed.因此,如果您的时间戳等于 2020-12-03T05:35:59.398 UTC 并且您的时区是亚洲/加尔各答,那么时间将转换为亚洲/加尔各答时区和字符串
2020-12-03 11:05:59
返回并打印。
You have nothing good to use the old-fashioned java.sql.Timestamp
class for.你没有什么好用的老式
java.sql.Timestamp
class 。 It was originally meant for transferring timestamp values with and without time zone to and from SQL databases.它最初用于在 SQL 数据库之间传输带和不带时区的时间戳值。 Since JDBC 4.2 we prefer
OffsetDateTime
, Instant
and LocalDateTime
for that purpose.由于 JDBC 4.2 我们更喜欢
OffsetDateTime
, Instant
和LocalDateTime
为此目的。 So just forget about the Timestamp
class.所以忘记
Timestamp
class。
Oracle tutorial: Date Time explaining how to use java.time. Oracle 教程:日期时间解释如何使用 java.time。
Is there even a format for timestamp with wierd + in between 398+0000?
在 398 + 0000 之间是否有带有奇怪 + 的时间戳格式?
The 398
part is fraction-of-second (millisecond) while the +0000
part is the zone offset part. 398
部分是秒的分数(毫秒),而+0000
部分是区域偏移部分。
You can parse 2020-12-03T05:35:59.398+0000
into an OffsetDateTime
using the format pattern, uuuu-MM-dd'T'HH:mm:ss.SSSX
.您可以使用格式模式
uuuu-MM-dd'T'HH:mm:ss.SSSX
将2020-12-03T05:35:59.398+0000
解析为OffsetDateTime
。
Demo:演示:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String text = "2020-12-03T05:35:59.398+0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
System.out.println(odt);
}
}
Output: Output:
2020-12-03T05:35:59.398Z
Check the DateTimeFormatter documentation page to learn more about the letters used for formatting.查看DateTimeFormatter 文档页面以了解有关用于格式化的字母的更多信息。
You can use isBefore
and isAfter
functions of OffsetDateTime
to compare its two instances.您可以使用
isBefore
的OffsetDateTime
和isAfter
函数来比较它的两个实例。
Demo:演示:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String text = "2020-12-03T05:35:59.398+0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
OffsetDateTime odtNow = OffsetDateTime.now();
System.out.println(odtNow.isBefore(odt));
System.out.println(odtNow.isAfter(odt));
}
}
Output: Output:
false
true
Learn more about the modern date-time API at Trail: Date Time .在Trail: Date Time中了解有关现代日期时间 API 的更多信息。 If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project .
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project .
The date-time API of java.util
and their formatting API, SimpleDateFormat
are outdated and error-prone. java.util 的日期时间
java.util
及其格式 API、 SimpleDateFormat
已过时且容易出错。 It is recommended to stop using them completely and switch to the modern date-time API .建议完全停止使用它们并切换到现代日期时间 API 。 Since
java.sql.Timestamp
extends java.util.Date
, it is recommended to stop using that as well.由于
java.sql.Timestamp
扩展java.util.Date
,因此建议也停止使用它。 However, for any reason, if you still want to use conversion between the modern and the legacy date-time API, use Instant
as the bridge.但是,无论出于何种原因,如果您仍想在现代日期时间和旧日期时间 API 之间使用转换,请使用
Instant
作为桥梁。
import java.sql.Timestamp;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String text = "2020-12-03T05:35:59.398+0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
Instant instant = odt.toInstant();
Timestamp timestamp = new Timestamp(instant.toEpochMilli());
System.out.println(timestamp);
}
}
Output: Output:
2020-12-03 05:35:59.398
You can use a custom DateFormatter
for non-standard formats.您可以将自定义
DateFormatter
用于非标准格式。 Here is a working example for your use case.这是您的用例的工作示例。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import static java.time.temporal.ChronoField.*;
public class Main {
private static final DateTimeFormatter INPUT_NON_STANDARD_FORMAT;
static {
INPUT_NON_STANDARD_FORMAT =
new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendLiteral('.')
.appendValue(MILLI_OF_SECOND, 3)
.appendLiteral("+0000")
.toFormatter();
}
public static void main(String[] args) {
String timestamp = "2020-12-03T05:35:59.398+0000";
final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(timestamp, INPUT_NON_STANDARD_FORMAT);
System.out.println(localDateTime.format(dateTimeFormatter));
}
}
Output Output
2020-12-03 05:35:59
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.