如何解析格式为 yyyy-MM-ddTHH:mm:ss.SSS+ZZZZ 的 UTC 时间戳
How to parse UTC timestamp of format yyyy-MM-ddTHH:mm:ss.SSS+ZZZZ
我在流式批处理中收到 String
格式的 2020-12-03T05:35:59.398+0000
时间戳。
我只想要 2020-12-03 05:35:59
作为 java.sql.Timestamp
实例,以便能够将它与其他 Timestamp
实例进行比较。
使用 Timestamp.valueOf()
函数出现以下错误:
Exception in thread "main" java.time.format.DateTimeParseException : Text '2020-12-03T05:35:59.398+0000' could not be parsed at index 23
我尝试了 给出的答案,确实发生了转换,但时间更改为 2020-12-03 11:05:59
我已经尝试在给定的格式之间进行更改 here 但仍然没有解决方案。
在 398+0000
之间甚至有一个带有奇怪 +
的时间戳格式吗?
您可以对非标准格式使用自定义 DateFormatter
。这是您的用例的工作示例。
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));
}
}
输出
2020-12-03 05:35:59
java.time
我建议您使用 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");
}
这个例子的输出是:
2020-12-03T05:35:59.398+0000 is earlier
上面前一个字符串中的 +0000
是与 UTC 的偏移量 — 00 小时 00 分钟的偏移量。因为它是零,我们知道时间是 UTC 时间。我不知道另一个字符串的时区或 UTC 偏移量。你需要知道,否则你会得到不正确的结果。在上面的代码中,我假设另一个字符串也是 UTC。
不要使用时间戳
I tried the answer given here, and conversion did happen but the time
was changed to 2020-12-03 11:05:59
这就是 Timestamp
class 的混乱程度。您获得了正确的时间戳值。当您 print Timestamp
对象时,会发生什么情况,即您正在(隐式或显式)调用它的 toString
方法。 Timestamp.toString()
混淆地使用 JVM 的默认时区来呈现字符串。因此,如果您的时间戳等于 2020-12-03T05:35:59.398 UTC,并且您的时区是 Asia/Kolkata,那么时间将转换为 Asia/Kolkata 时区和字符串 2020-12-03 11:05:59
返回并打印。
老式的java.sql.Timestamp
class你没什么好用的。它最初用于在 SQL 数据库之间传输带时区和不带时区的时间戳值。从 JDBC 4.2 开始,我们更喜欢 OffsetDateTime
、Instant
和 LocalDateTime
。所以忘记 Timestamp
class.
Link
Oracle tutorial: Date Time 解释如何使用 java.time.
Is there even a format for timestamp with wierd + in between 398+0000?
398
部分是秒的小数部分(毫秒),而+0000
部分是区域偏移部分。
您可以使用格式模式 uuuu-MM-dd'T'HH:mm:ss.SSSX
.
将 2020-12-03T05:35:59.398+0000
解析为 OffsetDateTime
演示:
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);
}
}
输出:
2020-12-03T05:35:59.398Z
查看 DateTimeFormatter documentation page 以了解有关用于格式化的字母的更多信息。
您可以使用 OffsetDateTime
的 isBefore
和 isAfter
函数来比较它的两个实例。
演示:
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));
}
}
输出:
false
true
在 Trail: Date Time. 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 .
了解有关现代日期时间 API 的更多信息
java.util
的日期时间 API 及其格式 API、SimpleDateFormat
已过时且容易出错。建议完全停止使用它们,转而使用modern date-time API. Since java.sql.Timestamp
extends java.util.Date
, it is recommended to stop using that as well. However, for any reason, if you still want to use conversion between the modern and the legacy date-time API, use 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);
}
}
输出:
2020-12-03 05:35:59.398
我在流式批处理中收到 String
格式的 2020-12-03T05:35:59.398+0000
时间戳。
我只想要 2020-12-03 05:35:59
作为 java.sql.Timestamp
实例,以便能够将它与其他 Timestamp
实例进行比较。
使用 Timestamp.valueOf()
函数出现以下错误:
Exception in thread "main" java.time.format.DateTimeParseException : Text '2020-12-03T05:35:59.398+0000' could not be parsed at index 23
我尝试了 2020-12-03 11:05:59
我已经尝试在给定的格式之间进行更改 here 但仍然没有解决方案。
在 398+0000
之间甚至有一个带有奇怪 +
的时间戳格式吗?
您可以对非标准格式使用自定义 DateFormatter
。这是您的用例的工作示例。
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));
}
}
输出
2020-12-03 05:35:59
java.time
我建议您使用 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");
}
这个例子的输出是:
2020-12-03T05:35:59.398+0000 is earlier
上面前一个字符串中的 +0000
是与 UTC 的偏移量 — 00 小时 00 分钟的偏移量。因为它是零,我们知道时间是 UTC 时间。我不知道另一个字符串的时区或 UTC 偏移量。你需要知道,否则你会得到不正确的结果。在上面的代码中,我假设另一个字符串也是 UTC。
不要使用时间戳
I tried the answer given here, and conversion did happen but the time was changed to
2020-12-03 11:05:59
这就是 Timestamp
class 的混乱程度。您获得了正确的时间戳值。当您 print Timestamp
对象时,会发生什么情况,即您正在(隐式或显式)调用它的 toString
方法。 Timestamp.toString()
混淆地使用 JVM 的默认时区来呈现字符串。因此,如果您的时间戳等于 2020-12-03T05:35:59.398 UTC,并且您的时区是 Asia/Kolkata,那么时间将转换为 Asia/Kolkata 时区和字符串 2020-12-03 11:05:59
返回并打印。
老式的java.sql.Timestamp
class你没什么好用的。它最初用于在 SQL 数据库之间传输带时区和不带时区的时间戳值。从 JDBC 4.2 开始,我们更喜欢 OffsetDateTime
、Instant
和 LocalDateTime
。所以忘记 Timestamp
class.
Link
Oracle tutorial: Date Time 解释如何使用 java.time.
Is there even a format for timestamp with wierd + in between 398+0000?
398
部分是秒的小数部分(毫秒),而+0000
部分是区域偏移部分。
您可以使用格式模式 uuuu-MM-dd'T'HH:mm:ss.SSSX
.
2020-12-03T05:35:59.398+0000
解析为 OffsetDateTime
演示:
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);
}
}
输出:
2020-12-03T05:35:59.398Z
查看 DateTimeFormatter documentation page 以了解有关用于格式化的字母的更多信息。
您可以使用 OffsetDateTime
的 isBefore
和 isAfter
函数来比较它的两个实例。
演示:
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));
}
}
输出:
false
true
在 Trail: Date Time. 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
java.util
的日期时间 API 及其格式 API、SimpleDateFormat
已过时且容易出错。建议完全停止使用它们,转而使用modern date-time API. Since java.sql.Timestamp
extends java.util.Date
, it is recommended to stop using that as well. However, for any reason, if you still want to use conversion between the modern and the legacy date-time API, use 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);
}
}
输出:
2020-12-03 05:35:59.398