Joda time plusDays 得到错误的日期
Joda time plusDays getting wrong date
我正在使用此代码:
DateTime(date)//Thu Aug 06 00:00:00 GMT+03:00 2020
.plusDays(days) // 103
.toDate()
结果是 Fri Dec 18 23:00:00 GMT+02:00 2020
而不是 Dec 19
。
对于某些日期它运行良好,对于其他结果 date-1,我猜问题出在一个月中的天数上,但是 plusDays()
不考虑它吗?
With some dates it work well, with other the result date-1, I guess
the problem is with number of days in month, but does plusDays() not
consider it?
确实考虑到了。您提到的两个 date-time 字符串的问题在于它们属于不同的 Zone-Offset (第一个是 UTC+3,第二个是 UTC+2)。下面给出了如何使用相同的 Zone-Offset.
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
我推荐你使用modern java.time
date-time API and the corresponding formatting API (package, java.time.format
). Learn more about the modern date-time API from Trail: Date Time. If your Android API level is still not compliant with Java8, check and Java 8+ APIs available through desugaring。
下面的table显示一个overview of modern date-time classes:
与现代date-time 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
您可以使用 java.time
,较低的 Android API 支持它,因为现在有 API desugaring in Android。
有一个 zone-aware class (java.time.ZonedDateTime
) 和一个 offset-aware (java.time.OffsetDateTime
),但是你的例子 String
只包含GMT / UTC 的偏移量。这就是为什么我会使用 OffsetDateTime
来解析确切的时间然后添加一天。
这是一个简单的示例,它定义了一个格式化程序,它解析给定的 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
如果您只对输出日期感兴趣(没有时间部分或偏移量),在那些 classes 中还有另一个方便的东西,那就是轻松提取日期或 time-part。您可以使用 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 datePicker
,您可以通过 getYear()
、getMonth()
和 getDayOfMonth()
接收选定的值,然后创建一个
LocalDate localDate = LocalDate.of(datePicker.getYear(),
datePicker.getMonth(),
datePicker.getDayOfMonth());
然后通过 localDate.plusDays(1);
添加一天
我正在使用此代码:
DateTime(date)//Thu Aug 06 00:00:00 GMT+03:00 2020
.plusDays(days) // 103
.toDate()
结果是 Fri Dec 18 23:00:00 GMT+02:00 2020
而不是 Dec 19
。
对于某些日期它运行良好,对于其他结果 date-1,我猜问题出在一个月中的天数上,但是 plusDays()
不考虑它吗?
With some dates it work well, with other the result date-1, I guess the problem is with number of days in month, but does plusDays() not consider it?
确实考虑到了。您提到的两个 date-time 字符串的问题在于它们属于不同的 Zone-Offset (第一个是 UTC+3,第二个是 UTC+2)。下面给出了如何使用相同的 Zone-Offset.
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
我推荐你使用modern java.time
date-time API and the corresponding formatting API (package, java.time.format
). Learn more about the modern date-time API from Trail: Date Time. If your Android API level is still not compliant with Java8, check
下面的table显示一个overview of modern date-time classes:
与现代date-time 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
您可以使用 java.time
,较低的 Android API 支持它,因为现在有 API desugaring in Android。
有一个 zone-aware class (java.time.ZonedDateTime
) 和一个 offset-aware (java.time.OffsetDateTime
),但是你的例子 String
只包含GMT / UTC 的偏移量。这就是为什么我会使用 OffsetDateTime
来解析确切的时间然后添加一天。
这是一个简单的示例,它定义了一个格式化程序,它解析给定的 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
如果您只对输出日期感兴趣(没有时间部分或偏移量),在那些 classes 中还有另一个方便的东西,那就是轻松提取日期或 time-part。您可以使用 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 datePicker
,您可以通过 getYear()
、getMonth()
和 getDayOfMonth()
接收选定的值,然后创建一个
LocalDate localDate = LocalDate.of(datePicker.getYear(),
datePicker.getMonth(),
datePicker.getDayOfMonth());
然后通过 localDate.plusDays(1);