在 java 夏令时后获取给定范围内的所有日期
Getting all the dates in the given range after daylight time saving in java
我有一个时间范围,其开始时间和结束时间都是 UTC。
本地时间在日期范围内的所有日期都保持不变。这就是为什么如果结束日期在夏令时结束之后,UTC 日期将更改 1 小时。即假设开始日期是 10 月 23 日,结束日期是 11 月 11 日凌晨 2 点 US/pacific。所以我在 UTC 中的范围变成 10/23 09:00 AM UTC 到 11/11 10:00 AM UTC。
我想获取 UTC 时间范围内的所有日期。如果我继续从开始日期开始添加一天,在夏令时之后,UTC 时间将保持不变,这就是为什么当地时间将关闭 1 小时。即在上面的示例中,如果我在夏令时后继续从 10/23 09:00 添加一天,我将收到的日期是 (11/03 09:00 UTC),(11/04 09:00 UTC), (11/05 09 UTC) 等等。太平洋标准时间 01:00 上午。 java 中是否有任何方法可以在时间范围内获取日期时间,以便在 11/02 之前我将获得“11/02 09:00 UTC”,从 11/03 开始我将获得“11/ 03 10:00 UTC"?
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class MyClass {
public static void main(String args[]) throws Exception{
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
convert(date1, date2);
}
private static void convert(String date1, String date2) throws Exception{
SimpleDateFormat localDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");
DateTimeFormatter formatter = DateTimeFormat.forPattern("E MMM dd HH:mm:ss z yyyy");
DateTime sDate = formatter.parseDateTime(date1);
DateTime eDate = formatter.parseDateTime(date2);
while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
Date finaldate = sDate.toDate();
System.out.println(localDateFormat.format(finaldate));
sDate = sDate.plusDays(1);
}
}
}
以下代码的输出是:
Thu Oct 24 11:30:00 GMT 2019
Fri Oct 25 11:30:00 GMT 2019
Sat Oct 26 11:30:00 GMT 2019
Sun Oct 27 11:30:00 GMT 2019
Mon Oct 28 11:30:00 GMT 2019
Tue Oct 29 11:30:00 GMT 2019
Wed Oct 30 11:30:00 GMT 2019
Thu Oct 31 11:30:00 GMT 2019
Fri Nov 01 11:30:00 GMT 2019
Sat Nov 02 11:30:00 GMT 2019
Sun Nov 03 11:30:00 GMT 2019
Mon Nov 04 11:30:00 GMT 2019
但是从 11 月 3 日开始,我试图获取 12:30,因为本地时区的时间保持不变。我试图实现的是时间,以便本地时区的时间保持不变。即到 11 月 2 日,11:30 UTC 转换为 4:30 PST。夏令时结束后,当地时区时间将保持不变。所以在 UTC 中,我试图在夏令时结束后获得 12:30。
ZonedDateTime 来自 java.time
我认为优雅的解决方案使用 java.time,现代 Java 日期和时间 API。您可能会认为它是您使用的 Joda-Time 库的继承者。我们需要的是 java.time.
中的 ZonedDateTime
class
ZoneId zone = ZoneId.of("America/Los_Angeles");
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
ZonedDateTime startDateTime = ZonedDateTime.parse(date1, formatter)
.withZoneSameInstant(zone);
ZonedDateTime endDateTime = ZonedDateTime.parse(date2, formatter)
.withZoneSameInstant(zone);
while (! startDateTime.isAfter(endDateTime)) {
Instant gmt = startDateTime.toInstant();
System.out.println(startDateTime + " GMT: " + gmt);
startDateTime = startDateTime.plusDays(1);
}
此片段的输出是:
2019-10-23T04:30-07:00[America/Los_Angeles] GMT: 2019-10-23T11:30:00Z
2019-10-24T04:30-07:00[America/Los_Angeles] GMT: 2019-10-24T11:30:00Z
2019-10-25T04:30-07:00[America/Los_Angeles] GMT: 2019-10-25T11:30:00Z
… (cut) …
2019-11-01T04:30-07:00[America/Los_Angeles] GMT: 2019-11-01T11:30:00Z
2019-11-02T04:30-07:00[America/Los_Angeles] GMT: 2019-11-02T11:30:00Z
2019-11-03T04:30-08:00[America/Los_Angeles] GMT: 2019-11-03T12:30:00Z
2019-11-04T04:30-08:00[America/Los_Angeles] GMT: 2019-11-04T12:30:00Z
您看到 GMT 时间从 11 月 3 日起从 11:30 变为 12:30。
如果您希望按照您的问题格式化输出:
ZoneId gmtZone = ZoneId.of("Etc/GMT");
while (! startDateTime.isAfter(endDateTime)) {
ZonedDateTime gmtTime = startDateTime.withZoneSameInstant(gmtZone);
System.out.println(gmtTime.format(formatter));
startDateTime = startDateTime.plusDays(1);
}
Wed Oct 23 11:30:00 GMT 2019
Thu Oct 24 11:30:00 GMT 2019
… (cut) …
Sun Nov 03 12:30:00 GMT 2019
Mon Nov 04 12:30:00 GMT 2019
乔达时间
出于两个原因,我对提出 Joda-Time 解决方案犹豫不决。第一,Joda-Time 项目处于维护模式,对于新代码,您应该更喜欢 java.time。第二,我不太精通 Joda-Time,所以我的解决方案可能不是最优雅的。我没有发现 ZonedDateTime
的 Joda-Time 等价物,所以我使用它的 LocalDateTime
,这都需要更多的转换并且更脆弱,因为 datetime 对象不知道它自己的时区。
DateTimeZone.setDefault(DateTimeZone.forID("Etc/GMT"));
DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles");
DateTimeZone gmtZone = DateTimeZone.forID("Etc/GMT");
DateTimeFormatter formatter
= DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zzz yyyy")
.withLocale(Locale.ROOT);
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
LocalDateTime sDate = formatter.parseDateTime(date1)
.withZone(zone)
.toLocalDateTime();
LocalDateTime eDate = formatter.parseDateTime(date2)
.withZone(zone)
.toLocalDateTime();
while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
DateTime finaldate = sDate.toDateTime(zone).withZone(gmtZone);
System.out.println(finaldate.toString(formatter));
sDate = sDate.plusDays(1);
}
Wed Oct 23 11:30:00 GMT 2019
Thu Oct 24 11:30:00 GMT 2019
… (cut) …
Sat Nov 02 11:30:00 GMT 2019
Sun Nov 03 12:30:00 GMT 2019
Mon Nov 04 12:30:00 GMT 2019
在任何情况下都应避免使用设计不佳且早已过时的 Date
和 SimpleDateFormat
classes。唯一的例外是,如果您需要一个老式的 Date
对象用于遗留 API,而您现在无力升级。在这种情况下,就在调用旧版 API.
之前进行转换
Link
- Oracle tutorial: Date Time 解释如何使用 java.time。
我有一个时间范围,其开始时间和结束时间都是 UTC。
本地时间在日期范围内的所有日期都保持不变。这就是为什么如果结束日期在夏令时结束之后,UTC 日期将更改 1 小时。即假设开始日期是 10 月 23 日,结束日期是 11 月 11 日凌晨 2 点 US/pacific。所以我在 UTC 中的范围变成 10/23 09:00 AM UTC 到 11/11 10:00 AM UTC。
我想获取 UTC 时间范围内的所有日期。如果我继续从开始日期开始添加一天,在夏令时之后,UTC 时间将保持不变,这就是为什么当地时间将关闭 1 小时。即在上面的示例中,如果我在夏令时后继续从 10/23 09:00 添加一天,我将收到的日期是 (11/03 09:00 UTC),(11/04 09:00 UTC), (11/05 09 UTC) 等等。太平洋标准时间 01:00 上午。 java 中是否有任何方法可以在时间范围内获取日期时间,以便在 11/02 之前我将获得“11/02 09:00 UTC”,从 11/03 开始我将获得“11/ 03 10:00 UTC"?
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class MyClass {
public static void main(String args[]) throws Exception{
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
convert(date1, date2);
}
private static void convert(String date1, String date2) throws Exception{
SimpleDateFormat localDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");
DateTimeFormatter formatter = DateTimeFormat.forPattern("E MMM dd HH:mm:ss z yyyy");
DateTime sDate = formatter.parseDateTime(date1);
DateTime eDate = formatter.parseDateTime(date2);
while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
Date finaldate = sDate.toDate();
System.out.println(localDateFormat.format(finaldate));
sDate = sDate.plusDays(1);
}
}
}
以下代码的输出是:
Thu Oct 24 11:30:00 GMT 2019
Fri Oct 25 11:30:00 GMT 2019
Sat Oct 26 11:30:00 GMT 2019
Sun Oct 27 11:30:00 GMT 2019
Mon Oct 28 11:30:00 GMT 2019
Tue Oct 29 11:30:00 GMT 2019
Wed Oct 30 11:30:00 GMT 2019
Thu Oct 31 11:30:00 GMT 2019
Fri Nov 01 11:30:00 GMT 2019
Sat Nov 02 11:30:00 GMT 2019
Sun Nov 03 11:30:00 GMT 2019
Mon Nov 04 11:30:00 GMT 2019
但是从 11 月 3 日开始,我试图获取 12:30,因为本地时区的时间保持不变。我试图实现的是时间,以便本地时区的时间保持不变。即到 11 月 2 日,11:30 UTC 转换为 4:30 PST。夏令时结束后,当地时区时间将保持不变。所以在 UTC 中,我试图在夏令时结束后获得 12:30。
ZonedDateTime 来自 java.time
我认为优雅的解决方案使用 java.time,现代 Java 日期和时间 API。您可能会认为它是您使用的 Joda-Time 库的继承者。我们需要的是 java.time.
中的ZonedDateTime
class
ZoneId zone = ZoneId.of("America/Los_Angeles");
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
ZonedDateTime startDateTime = ZonedDateTime.parse(date1, formatter)
.withZoneSameInstant(zone);
ZonedDateTime endDateTime = ZonedDateTime.parse(date2, formatter)
.withZoneSameInstant(zone);
while (! startDateTime.isAfter(endDateTime)) {
Instant gmt = startDateTime.toInstant();
System.out.println(startDateTime + " GMT: " + gmt);
startDateTime = startDateTime.plusDays(1);
}
此片段的输出是:
2019-10-23T04:30-07:00[America/Los_Angeles] GMT: 2019-10-23T11:30:00Z 2019-10-24T04:30-07:00[America/Los_Angeles] GMT: 2019-10-24T11:30:00Z 2019-10-25T04:30-07:00[America/Los_Angeles] GMT: 2019-10-25T11:30:00Z … (cut) … 2019-11-01T04:30-07:00[America/Los_Angeles] GMT: 2019-11-01T11:30:00Z 2019-11-02T04:30-07:00[America/Los_Angeles] GMT: 2019-11-02T11:30:00Z 2019-11-03T04:30-08:00[America/Los_Angeles] GMT: 2019-11-03T12:30:00Z 2019-11-04T04:30-08:00[America/Los_Angeles] GMT: 2019-11-04T12:30:00Z
您看到 GMT 时间从 11 月 3 日起从 11:30 变为 12:30。
如果您希望按照您的问题格式化输出:
ZoneId gmtZone = ZoneId.of("Etc/GMT");
while (! startDateTime.isAfter(endDateTime)) {
ZonedDateTime gmtTime = startDateTime.withZoneSameInstant(gmtZone);
System.out.println(gmtTime.format(formatter));
startDateTime = startDateTime.plusDays(1);
}
Wed Oct 23 11:30:00 GMT 2019 Thu Oct 24 11:30:00 GMT 2019 … (cut) … Sun Nov 03 12:30:00 GMT 2019 Mon Nov 04 12:30:00 GMT 2019
乔达时间
出于两个原因,我对提出 Joda-Time 解决方案犹豫不决。第一,Joda-Time 项目处于维护模式,对于新代码,您应该更喜欢 java.time。第二,我不太精通 Joda-Time,所以我的解决方案可能不是最优雅的。我没有发现 ZonedDateTime
的 Joda-Time 等价物,所以我使用它的 LocalDateTime
,这都需要更多的转换并且更脆弱,因为 datetime 对象不知道它自己的时区。
DateTimeZone.setDefault(DateTimeZone.forID("Etc/GMT"));
DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles");
DateTimeZone gmtZone = DateTimeZone.forID("Etc/GMT");
DateTimeFormatter formatter
= DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zzz yyyy")
.withLocale(Locale.ROOT);
String date1 = "Wed Oct 23 11:30:00 GMT 2019";
String date2 = "Mon Nov 04 12:30:00 GMT 2019";
LocalDateTime sDate = formatter.parseDateTime(date1)
.withZone(zone)
.toLocalDateTime();
LocalDateTime eDate = formatter.parseDateTime(date2)
.withZone(zone)
.toLocalDateTime();
while(eDate.isAfter(sDate) || eDate.equals(sDate)) {
DateTime finaldate = sDate.toDateTime(zone).withZone(gmtZone);
System.out.println(finaldate.toString(formatter));
sDate = sDate.plusDays(1);
}
Wed Oct 23 11:30:00 GMT 2019 Thu Oct 24 11:30:00 GMT 2019 … (cut) … Sat Nov 02 11:30:00 GMT 2019 Sun Nov 03 12:30:00 GMT 2019 Mon Nov 04 12:30:00 GMT 2019
在任何情况下都应避免使用设计不佳且早已过时的 Date
和 SimpleDateFormat
classes。唯一的例外是,如果您需要一个老式的 Date
对象用于遗留 API,而您现在无力升级。在这种情况下,就在调用旧版 API.
Link
- Oracle tutorial: Date Time 解释如何使用 java.time。