时区的 Java 日期问题



我为此苦苦挣扎了好几天。

我有一个日期字段,它给出了"yyyy-MM-dd"格式的日期。

我的对象有这样的字段

@Temporal(TemporalType.DATE)
private Date finishdate;
我在 UTC 上,

这需要在世界各地工作,所以在 UTC-7 或 UTC+7 上

在数据库上,此值需要存储 0 小时。

填写完成日期后,格式会给我时区,例如:

想要 2014-10-01,零小时和分钟和秒,在不同的时区我捕捉到:

2014-10-01 07:00:00:000或2014-09-01 17:00:00:000

问题接缝是因为日期 liybrary,我已经找到了 JODA 库的解决方案,但我被告知不要使用它,我需要找到另一个解决方案。

因此,需要转换为UTC日期,所有日期或其他内容,但日期必须相同,例如10月1日。

有人通过这个吗?

Joda-Time 库修复了这样的问题,我相信这也是 Java 8 中 java.time 包的基础,但对于较旧的 Java 版本,这种问题经常发生。

在没有 Joda 时间的情况下,我看到的唯一一致的处理方法是将纯日期视为字符串 ("2014-10-01"( 或整数类型 (20141001( 而不是日期。 并且仅在计算中需要时才转换为日期。 不过,这真的很痛苦。

不要忘记 SimpleDateFormat 不是线程安全的。saga56 给出的答案可能有效,但如果同时使用反序列化器,您将有一些非常奇怪的日期。您需要每次都"新建"SimpleDateFormat,或者(不太有利(做其他事情以确保SimpleDateFormat一次严格限制为1个线程。

此问题

的解决方案。

我们为 Date 类型的每个对象制作了一个自定义反序列化程序。

在我们序列化或反序列化的 ObjectMapperFactory 上,我映射到另一个类,如下所示:

 module.addDeserializer(Date.class, new DateDeserializerByDefault());

然后,在这个课程中,我们做到了:

private static SimpleDateFormat dateFormatWithoutTimezome = new SimpleDateFormat("yyyy-MM-dd");
private static SimpleDateFormat dateFormatWithTimezone= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
private static Pattern pattern = Pattern.compile("([0-9]{4})-([0-9]{2})-([0-9]{2})");
@Override
public Date deserialize(JsonParser jparser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    String content = jparser.getValueAsString();
    DateFormat format=(pattern.matcher(content).matches()) ? dateFormatWithoutTimezome : dateFormatWithTimezone;        
try {
    return format.parse(content);
} catch (ParseException e) {
    throw new JsonParseException("Date parse failed", jparser.getCurrentLocation(),e);
}
}

有了这个,当我们收到不同格式的日期或时区时,我们可以将其更改为我们想要的。

我希望这个解决方案可以提供帮助,我被困了 3,5 天。枣子是a**的痛苦。

其他答案是正确的,但已经过时了。

java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,如java.util.Date.Calendarjava.text.SimpleDateFormat。Joda-Time 团队还建议迁移到 java.time。

要了解更多信息,请参阅 Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。

Java.time的大部分功能在ThreeTen-Backport中向后移植到Java 6和7,并在ThreeTenABP中进一步适应Android。

LocalDate

LocalDate表示没有时间且没有时区的仅日期值。

您的输入字符串采用标准 ISO 8601 格式,因此可以通过 LocalDate 直接解析。无需指定格式模式。

String input = "2014-10-01";
LocalDate localDate = LocalDate.parse( input );

ZonedDateTime

您假设一天从时间开始00:00:00 .但情况并非总是如此。在某些时区,夏令时 (DST( 或其他异常可能意味着一天从时钟上的其他时间开始,例如 01:00:00 。让 java.time 确定一天中第一个时刻的开始时间。指定一个时区,并假设与 Java 捆绑在一起的 tz 数据库是最新的,则调用 LocalDate::atStartOfDay 会为您的日期和第一个时刻生成一个ZonedDateTime

ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = localDate.atStartOfDay( zoneId );

如果你想要一天中的第一个时刻采用UTC,请指定常量ZoneOffset.UTC(ZoneOffsetZoneId的子类(。

ZonedDateTime zdt = localDate.atStartOfDay( ZoneOffset.UTC );

或者,使用更合适的OffsetDateTime类。这适用于仅具有 UTC 偏移量但缺少处理异常(如在完整时区中发现的 DST(的规则集的值。在UTC中,一天总是从存储在常量LocalTime.MIN中的00:00:00开始。

OffsetTime ot = OffsetTime.of( LocalTime.MIN , ZoneOffset.UTC );
OffsetDateTime odt = localDate.atTime( offsetTime );

数据库

对于数据库工作,如果要存储仅日期值,则应使用与 SQL 标准类型DATE 类似的数据类型。

对于日期时间值,几乎每个严肃的数据库都将传入数据转换为 UTC,以便在TIMESTAMP WITH TIME ZONE类型列中存储。您的 JDBC 驱动程序应该对此有所帮助。但是测试和实验,因为驱动程序和数据库的行为差异很大。

在 JDBC 4.2 及更高版本中,您可以直接通过 setObject/getObject 传递/获取 java.time 类型。如果没有,则通过添加到旧类的新方法转换为 java.sql 类型。

相关内容

  • 没有找到相关文章

最新更新