最佳方法将 java.sql.TimeStamp 在 Java 中转换为 UTC 格式。

huangapple go评论67阅读模式
英文:

Best way to Change java.sql.TimeStamp to UTC format in Java

问题

我已尝试多种方法之一是使用SimpleDateFormatter,现在尝试如下:

import java.sql.Timestamp;
public static String getCorrectTimeFormat(Timestamp time) {
    return time.toInstant().toString();
}

但问题是,我在编写单元测试时意识到的,时间会被修改。

Timestamp timeStamp = Timestamp.valueOf("2020-07-22 12:26:51.599");
String res = UserUtil.getCorrectTimeFormat(timeStamp);
assertThat(res).isEqualTo("2020-07-22T12:26:51.599Z");

这始终无法通过,因为它会自动转换为"2020-07-22T11:26:51.599Z"。

英文:

I have tried multiple ways one of them using SimpleDateFromatter and now trying

import java.sql.Timestamp;
public static String getCorrectTimeFormat(Timestamp time) {
        return time.toInstant().toString();
    }

But the problem is which I realized during writing unit test is, the time gets modified.

  Timestamp timeStamp = Timestamp.valueOf("2020-07-22 12:26:51.599");
  String res = UserUtil.getCorrectTimeFormat(timeStamp);
  assertThat(res).isEqualTo("2020-07-22T12:26:51.599Z");

This never passes as the it auto converts to "2020-07-22T11:26:51.599Z"

答案1

得分: 2

  1. 最好完全避免使用 java.sql.Timestamp。我会向你展示如何做。
  2. 你得到的结果是正确的,正如我认为你已经发现的那样。

从数据库获取 java.time 类型

自从 JDBC 4.2 以来,我们可以直接从 ResultSet 中获取 java.time 类型。如果你的数据库值是 timestamp with time zone(推荐),例如:

	OffsetDateTime odt = rs.getObject(
			"your_timestamp_with_time_zone_column", OffsetDateTime.class);
	String utcString = odt.withOffsetSameInstant(ZoneOffset.UTC).toString();

如果你的数据库值是没有时区的 timestamp(不推荐),我们只能从中获取一个 LocalDateTime,它不定义一个特定的时间点。要转换为 Instant,我们需要知道数据库使用的时区。例如:

	ZoneId databaseTimeZone = ZoneId.of("Europe/Paris");
	LocalDateTime ldt = rs.getObject(
			"your_timestamp_column", LocalDateTime.class);
	String utcString = ldt.atZone(databaseTimeZone)
			.withZoneSameInstant(ZoneOffset.UTC)
			.toString();

如果你的数据库使用了以 UTC 为偏移量的时区,最好使用 ZoneOffset 而不是 ZoneId

	ZoneOffset databaseOffset = ZoneOffset.UTC;
	LocalDateTime ldt = rs.getObject(
			"your_timestamp_column", LocalDateTime.class);
	String utcString = ldt.atOffset(databaseOffset).toString();

你观察到的结果是正确的

java.sql.Timestamp 以 JVM 的默认时区混淆地打印,而 Timestamp.valueOf() 同样混淆地假设了那个时区。所以假设你的时区在今年的这个时间偏移量为 +01:00(比如英国、爱尔兰、葡萄牙、摩洛哥和突尼斯等),从 2020-07-22 12:26:51.5992020-07-22T11:26:51.599Z 的转换是正确的。

英文:
  1. It’s best to avoid jqva.sql.Timestamp completely. I’ll show you how.
  2. The result you got is correct, as I think you have already discovered.

Get java.time types from your database

Since JDBC 4.2 we can directly get java.time types from a ResultSet. If your database value is a timestamp with time zone (recommended), for example:

	OffsetDateTime odt = rs.getObject(
			"your_timestamp_with_time_zone_column", OffsetDateTime.class);
	String utcString = odt.withOffsetSameInstant(ZoneOffset.UTC).toString();

If your database value is a timestamp without time zone (not recommended), we can only get a LocalDateTime from it, which doesn’t define a point in time. To convert to Instant we need to rely on knowing which time zone the database uses. For example:

	ZoneId datebaseTimeZone = ZoneId.of("Europe/Paris");
	LocalDateTime ldt = rs.getObject(
			"your_timestamp_column", LocalDateTime.class);
	String utcString = ldt.atZone(datebaseTimeZone)
			.withZoneSameInstant(ZoneOffset.UTC)
			.toString();

If your database uses UTC, which counts as an offset, it’s better to use ZoneOffset than ZoneId:

	ZoneOffset datebaseOffset = ZoneOffset.UTC;
	LocalDateTime ldt = rs.getObject(
			"your_timestamp_column", LocalDateTime.class);
	String utcString = ldt.atOffset(datebaseOffset).toString();

Your observed result is correct

java.sql.Timestamp confusingly prints in the default time zone of the JVM, and Timestamp.valueOf() equally confusingly assumes that time zone. So assuming that your time zone is at offset +01:00 at this time of year (such as Great Britain, Ireland, Portugal, Morocco and Tunesia, for example), the conversion from 2020-07-22 12:26:51.599 to 2020-07-22T11:26:51.599Z is correct.

答案2

得分: 1

你可以使用 Java 8 的时间类 ZonedDateTime:

//1 - 默认格式
String timeStamp = "2019-03-27T10:15:30";
ZonedDateTime localTimeObj = ZonedDateTime.parse(timeStamp);

//2 - 指定格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss a z");
String timeStamp1 = "2019-03-27 10:15:30 AM";
ZonedDateTime localTimeObj1 = ZonedDateTime.parse(timeStamp1, formatter);

//从 ZonedDateTime 获取 LocalDate
LocalDate localDate = localTimeObj1.toLocalDate();

//从带有 UTC 时区的 ZonedDateTime 获取时间戳
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
Timestamp timestamp = Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
英文:

You can use java 8 time ZonedDateTime class :

//1 - default pattern
String timeStamp = "2019-03-27T10:15:30";
ZonedDateTime localTimeObj = ZonedDateTime.parse(time);

//2 - specified pattern
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss a z");
String timeStamp1 = "2019-03-27 10:15:30 AM";
ZonedDateTime localTimeObj1 = ZonedDateTime.parse(timeStamp1, formatter);

//To get LocalDate from ZonedDateTime
LocalDate localDate = localTimeObj1.toLocalDate()

//To get timestamp from zoneddatetime with utc timezone
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
Timestamp timestamp = Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());

huangapple
  • 本文由 发表于 2020年7月23日 20:45:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63054617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定