我为此苦苦挣扎了好几天。
我有一个日期字段,它给出了"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
、.Calendar
和java.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
(ZoneOffset
是ZoneId
的子类(。
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 类型。