【问题标题】:SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") parse in java gives wrong date?java中的SimpleDateFormat(“yyyy-MM-dd'T'HH:mm:ssZ”)解析给出错误的日期?
【发布时间】:2016-07-21 10:16:38
【问题描述】:

我使用了这个SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")。所以当我通过日期2016-01-01T10:30:00-0800 大于或等于 10:30:00-0800 时间时,它将解析(日期)响应,即第二天日期 2016-01-02T00: 00:00+0530 这不是预期的。它将日期更改了一天。如果我给出 2016-01-01T10:20:00-0800 然后给出确切的日期。所以如果时间应该少于 t10:30:00-0800 那么否则在第二天获得预期结果。

完整代码:

SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public Date deserialize(JsonParser jsonparser, DeserializationContext arg1)   {
  String date = jsonparser.getText();
  dt.parse(date);
}

【问题讨论】:

  • 你的语言环境是什么?
  • @abhay 应用服务器在 UTC 时间和印度本地机器上运行
  • 显示您的代码来演示确切的问题。
  • @Jesper 解析方法返回次日日期
  • 在上面编辑您的问题并添加代码;在 cmets 中发布代码效果不佳。

标签: java parsing datetime simpledateformat java.util.date


【解决方案1】:

重要的是要了解java.util.Date 类的实例不是日历日期而是时间点。

java.util.Date 转换为字符串表示和从字符串表示转换总是涉及时区。

您的输入是2016-01-01T10:30:00-0800,表示时区偏移为-8 小时(这是美国洛杉矶的时区)。该时刻对应于偏移量为 0 小时的区域中的2016-01-01T18:30:00+0000(如英国伦敦)或您当地时区中的2016-01-02T00:00:00+0530

如果您想存储洛杉矶会议开始的时刻并在不同时区显示该时刻,那很好。

如果您想表示没有固有时间信息的日期(如生日),您最好使用java.time.LocalDate(如果您使用 Java 8)或org.joda.time.LocalDate(如果 Java 8 不是一个选项)。

【讨论】:

  • 如果用户来自不同的区域,那么如果请求日期是根据他的本地时区,那么需要为该项目设置的日期是根据他的本地时区或 UTC 时间。因为它可能发生在同一日期对于美国用户有 1 月 1 日,印度用户将在第二天看到该日期。
【解决方案2】:

java.time

您正在使用旧的过时日期时间类,这些类已被证明设计不佳、令人困惑且麻烦。请改用 java.time。

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

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

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

ISO 8601

您的输入字符串符合ISO 8601 标准。这些标准格式在 java.time 类中默认使用。所以不需要指定格式模式。

偏移

您的输入值与 UTC 有一个偏移量,比 UTC 晚了 8 小时。

OffsetDateTime 类表示此类值。

OffsetDateTime odt = OffsetDateTime.parse( "2016-01-01T10:30:00-0800" );

时区

时区是与 UTC 的偏移量加上一组用于处理异常情况的规则,例如夏令时 (DST)。如果您确定要用作此值的上下文的时区,请将其应用以获取 ZonedDateTime

通过proper time zone namecontinent/region 的格式指定时区(ZoneId)。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = odt.atZone( zoneId );

更改时区

如果你想通过本地time in India的镜头看到这个值,你可以应用不同的时区来创建一个新的ZonedDateTime。 java.time 类使用immutable objects 模式。因此请注意,java.time 类不是更改(“改变”)现有对象的时区设置,而是基于原始对象的成员创建一个新对象及其一些成员。

ZonedDateTime zdt_Kolkata = zdt.withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ) ) ;

【讨论】:

  • 我无法将 java 版本 7 更改为 8,所以对于 java 7,你有什么替代方案吗?
猜你喜欢
  • 2013-12-08
  • 1970-01-01
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多