Joda time plus日期错误的日子

Joda time plusDays getting wrong date

提问人:Pavel Poley 提问时间:9/7/2020 更新时间:9/7/2020 访问量:848

问:

我正在使用此代码:

 DateTime(date)//Thu Aug 06 00:00:00 GMT+03:00 2020
                .plusDays(days) // 103
                .toDate()

结果是代替. 对于某些日期,它运行良好,对于其他结果日期-1,我想问题出在一个月的天数上,但没有考虑吗?Fri Dec 18 23:00:00 GMT+02:00 2020Dec 19plusDays()

java android 日期时间 jodatime android-jodatime

评论

1赞 deHaar 9/7/2020
您必须使用 JodaTime 还是可以使用 (Java 8+)?java-time
0赞 Pavel Poley 9/7/2020
如果 Android api 21+ 支持,所以我可以使用java-time
0赞 MC Emperor 9/7/2020
这可能是由于夏令时。10 月 25 日左右,时区偏移量从 +3 更改为 +2。

答:

2赞 Arvind Kumar Avinash 9/7/2020 #1

对于某些日期,它运行良好,对于其他日期,我猜结果日期-1 问题出在月中的天数上,但 plusDays() 没有 考虑一下?

它确实考虑过。您提到的两个日期时间字符串的问题在于它们属于不同的区域偏移量(第一个是 UTC+3,第二个是 UTC+2)。下面给出了如何使用相同的区域偏移量来做到这一点。

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zZ yyyy");
        DateTime dateTime = DateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);
        // With Zone-Offset of UTC+2
        System.out.println(dateTime.withZone(DateTimeZone.forOffsetHours(2)));

        // Add 103 days
        DateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);
        System.out.println(dateTime.withZone(DateTimeZone.forOffsetHours(2)));
    }
}

输出:

2020-08-05T21:00:00.000Z
2020-08-05T23:00:00.000+02:00
2020-11-16T21:00:00.000Z
2020-08-05T23:00:00.000+02:00

我建议您使用新式日期时间 API 和相应的格式化 API(package、)。从 Trail: Date Time 了解有关新式日期时间 API 的更多信息。如果您的 Android API 级别仍然不符合 Java8,请查看如何在 Android 项目中使用 ThreeTenABP通过脱糖提供的 Java 8+ APIjava.timejava.time.format

下表显示了新式日期时间类的概述enter image description here

使用新式日期时间 API:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // Define formatter for your date-time string
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O u");

        // Parse the given date0-time string into OffsetDateTime object
        OffsetDateTime dateTime = OffsetDateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);

        // Add 103 days to the OffsetDateTime object
        OffsetDateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);
    }
}

输出:

2020-08-06T00:00+03:00
2020-11-17T00:00+03:00

或者

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // Define formatter for your date-time string
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");

        // If you do not need Zone Id or Zone Offset information, you can go for
        // LocalDateTime
        LocalDateTime dateTime = LocalDateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);

        // You can convert LocalDateTime object into an OffsetDateTime by applying the
        // Zone-Offset e.g. the following line applies UTC+03:00 hours to LocalDateTime
        OffsetDateTime odt = dateTime.atOffset(ZoneOffset.ofHours(3));
        System.out.println(odt);

        // Add 103 days to the LocalDateTime object
        LocalDateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);

        odt = dateTimeAfter103Days.atOffset(ZoneOffset.ofHours(3));
        System.out.println(odt);
    }
}

输出:

2020-08-06T00:00
2020-08-06T00:00+03:00
2020-11-17T00:00
2020-11-17T00:00+03:00
3赞 deHaar 9/7/2020 #2

您可以使用它,并且在较低的 Android API 中受支持,因为现在 Android 中有 API 脱糖java.time

有一个区域感知类 () 和一个偏移感知类 (),但您的示例仅包含 GMT / UTC 的偏移量。这就是为什么我会使用 an 来解析确切的时间点,然后添加一天。java.time.ZonedDateTimejava.time.OffsetDateTimeStringOffsetDateTime

下面是一个简单的示例,它定义了一个格式化程序,该格式化程序解析给定的内容并将其用于输出:String

public static void main(String[] args) {
    // example String
    String date = "Fri Dec 18 23:00:00 GMT+02:00 2020";
    // create a formatter that is able to parse and output the String
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss OOOO uuuu",
                                                        Locale.ENGLISH);
    // parse the String using the formatter defined above
    OffsetDateTime odt = OffsetDateTime.parse(date, dtf);
    System.out.println("OffsetDateTime parsed is\t" + odt.format(dtf));
    
    // add a day to the date part
    OffsetDateTime dayLater = odt.plusDays(1);
    System.out.println("Adding a day results in\t\t" + dayLater.format(dtf));
}

这输出

OffsetDateTime parsed is    Fri Dec 18 23:00:00 GMT+02:00 2020
Adding a day results in     Sat Dec 19 23:00:00 GMT+02:00 2020

如果您只对输出日期(没有时间部分或偏移量)感兴趣,那么在这些类中还有另一个方便的事情,那就是轻松提取日期或时间部分。您可以使用 执行以下操作,例如:OffsetDateTime

// extract the part that only holds information about day of month, month of year and year
LocalDate dateOnly = odt.toLocalDate();
// print the default format (ISO standard)
System.out.println(dateOnly);
// or define and use a totally custom format
System.out.println(dateOnly.format(
                        DateTimeFormatter.ofPattern("EEEE, 'the' dd. 'of' MMMM uuuu",
                                                    Locale.ENGLISH)
                    )
);

那将输出

2020-12-18
Friday, the 18. of December 2020

如果您正在处理 ,您可以通过 和 接收选定的值,然后创建一个DatePicker datePickergetYear()getMonth()getDayOfMonth()

LocalDate localDate = LocalDate.of(datePicker.getYear(),
                                   datePicker.getMonth(), 
                                   datePicker.getDayOfMonth());

然后只需添加一天localDate.plusDays(1);

评论

0赞 Pavel Poley 9/7/2020
but your example String just contains an offset from GMT / UTC它实际上是来自 DatePicker 的 java Date 对象
0赞 deHaar 9/7/2020
@PavelPoley 您可以从 a 中获取年、月和月中的某一天,然后从中创建一个。由于您示例中的问题,我不会再使用。查看我编辑的答案...DatePickerLocalDatejava.util.Date
0赞 Pavel Poley 9/7/2020
为什么要使用?localDate.plusDays(1)
0赞 deHaar 9/7/2020
@PavelPoley这只是一个示例,您可以在那里输入任何内容。如果你有,那就做,没问题。intint days = 103;localDate.plusDays(days);