【问题标题】:time convert issue while converting adding one day extra转换时增加一天的时间转换问题
【发布时间】:2021-08-27 06:50:03
【问题描述】:

我正在尝试转换时区,但它从 java 函数中增加了一天。

   ""  deActivationDate=2021-06-25T23:59:59.000+0000"";
    
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

    try {
        Date date =formatter.parse(deActivationDate);
        deActivationDate=formatter.format(date);
        LOGGER.info("time format  printing 1" +deActivationDate);//2021-06-26T04:29:59.000+0430

        deActivationDate = deActivationDate.substring(0, deActivationDate.length()-2)+":30";

        LOGGER.info("time format  printing 2" +deActivationDate);//2021-06-26T04:29:59.000+04:30""

在上面的停用日期是 25,当我提供输入但在格式化程序解析方法之后,它转换为 26,为什么有一天操作系统会添加如何避免它。

【问题讨论】:

  • 上述日期为UTC +0:0时区,转换后的日期为UTC +4:30,正确。有什么问题?
  • 顺便说一句,你为什么不切换到“新”的 java.time api 来让事情变得更容易?
  • 如果格林威治时间是凌晨 12 点 (UTC +00:00),那么在您的手表中,时间将为凌晨 4:30,因为您距离时区中心 4.5 小时
  • 在解析日期之前,您可能想在日期格式化程序中添加特定时区 formatter.setTimeZone(TimeZone.getTimeZone("UTC"))
  • 这能回答你的问题吗? Changing timezone without changing time in Java

标签: java timezone java-7 datetime-format


【解决方案1】:

这是您的代码的修复方法。虽然我们建议不要通过 substring 方法来做。

String deActivationDate="2021-06-25T23:59:59.000+0000";
 
try {
  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
  formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
  Date date =formatter.parse(deActivationDate);
  deActivationDate=formatter.format(date);
  
  System.out.println("time format  printing 1: " +deActivationDate); 
  //2021-06-25T23:59:59.000+0000

  deActivationDate = deActivationDate.substring(0, 
  deActivationDate.length()-4)+"0430";
    
  System.out.println("time format  printing 2: " +deActivationDate); 
  //2021-06-25T23:59:59.000+0430

} catch (Exception e) {
  System.err.println(e.getMessage());
}

【讨论】:

  • 你说得非常正确,但是时区会在一段时间后更改为 03:30,所以我们不想在代码中手动更改,这就是我们没有添加子字符串的原因
【解决方案2】:

感谢大家的建议@beshambher-chaukhwan m 我已经通过以下代码实现了更改

String deActivationDate="2021-06-25T23:59:59.000+0000";
                         
                         SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
                         
                        try {
                            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
                            Date date =formatter.parse(deActivationDate);
                            deActivationDate=formatter.format(date);                    
                            if(TimeZone.getDefault().useDaylightTime()) {
                                  deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"04:30";
                            }else {         
                                  deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"03:30";
                            }

【讨论】:

  • 答案不正确。它全年打印+04:30。伊朗将回到标准时间并在 2021 年 9 月 22 日偏移 +03:30。我用字符串 2021-11-25T23:59:59.000+0000 尝试了你的代码,但仍然得到 time format printing 1: 2021-11-25T23:59:59.000+04:30useDaylightTime 方法只告诉您 时区使用夏令时(夏令时),而不是 一年中的哪个部分,所以它总是返回 true .
【解决方案3】:

java.time 到 ThreeTen Backport

您应该认真考虑使用现代 Java 日期和时间 API java.time 来处理重要的日期和时间工作。

你的问题不是很清楚,但我认为你想在你自己的时区将日期和时间字符串转换为相同的日期和挂钟时间,在这种情况下,亚洲/德黑兰时区。所以一个不同的时间点:在伊朗接近一天结束时,而不是在 UTC 接近一天结束时。并且在 UTC 偏移量中有一个冒号。

我声明了两个格式化程序,一个用于不带冒号的解析,一个用于格式化返回 冒号:

private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .appendPattern("xx")
        .toFormatter();

private static final DateTimeFormatter PRINTER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .appendPattern("xxx")
        .toFormatter();

现在您的转换如下所示:

    String deActivationDate = "2021-06-25T23:59:59.000+0000";
    
    OffsetDateTime dateTime = OffsetDateTime.parse(deActivationDate, PARSER);
    deActivationDate = dateTime.atZoneSimilarLocal(ZoneId.systemDefault())
            .format(PRINTER);
    System.out.println("time format  printing: " +deActivationDate);

输出是 — 在 Java 1.7.0_67 和 ThreeTen Backport 版本 1.3.6 上测试:

时间格式打印:2021-06-25T23:59:59+04:30

Java 知道亚洲/德黑兰时区在 6 月 25 日使用夏令时 (DST),因此转换为并打印您想要的偏移量 +04:30。如果日期在一年中的标准时间部分,则将打印 +03:30

不打印 0 毫秒,这在大多数情况下是一个优势。格式为 ISO 8601,根据 ISO 8601 标准,秒的小数部分为 0 时是可选的。如果您需要毫秒,请改用这个更简单的格式化程序:

private static final DateTimeFormatter PRINTER
        = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx");

时间格式打印:2021-06-25T23:59:59.000+04:30

半开:您不应在新一天开始前 1 秒表示一天结束。首先,这是错误的:一天不会在结束前一秒结束。其次,它可能会由于最后一秒内的时间而导致错误,因此在您的程序中既不属于某一天,也不属于另一天。即使这在实践中没有发生,你也会让程序员浪费他们的时间想知道它是否可能发生。而是将一天的结束表示为第二天唯一的第一时刻(通常是 00:00)。测试时,要求在一天结束之前严格属于一天。这种方法是各种间隔的标准,当然也适用于时间间隔。然后它们被称为半开区间

问题:java.time 不需要 Java 8 吗?

java.time 在 Java 7 上运行良好。它至少需要 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。
  • 在非 Android Java 6 和 7 中,获取 ThreeTen Backport,这是现代类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在较旧的 Android 上,请使用脱糖或 Android 版本的 ThreeTen Backport。它被称为 ThreeTenABP。在后一种情况下,请确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

  • 我强烈推荐任何使用 Java 6+ 的人使用这个答案。这将使代码在将来升级到更高版本的 Java 时易于移植。
猜你喜欢
  • 2020-07-17
  • 1970-01-01
  • 2018-08-27
  • 2020-07-07
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 2013-11-11
  • 1970-01-01
相关资源
最近更新 更多