时间转换问题,同时转换添加一天额外

问题描述

我正在尝试转换时区,但它从 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 为什么有一天操作系统会添加如何避免它。

解决方法

java.time 到 ThreeTen Backport

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

您的问题不是很清楚,但我认为您希望将日期和时间字符串转换为您自己时区中相同的日期和挂钟时间,在这种情况下,亚洲/德黑兰时区。所以一个不同的时间点:在伊朗接近一天结束时,而不是在 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,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
  • 在较旧的 Android 上,使用脱糖或 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。在后一种情况下,请确保使用子包从 org.threeten.bp 导入日期和时间类。

链接

,

这是您的代码的修复程序。虽然我们建议不要通过子字符串方法来做。

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());
}
,

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

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";
                            }