关于java:确定日期的夏令时的算法?

关于java:确定日期的夏令时的算法?

Algorithm to determine Daylight Saving Time of a date?

最初,我在Actionscript中寻找解决方案。 这个问题的关键是算法,当时钟必须切换夏令时时,它会检测确切的分钟。

因此,例如在10月25日至10月31日之间,我们必须检查一下,如果实际日期是星期天,则是在2点之前或之后...


没有真正的算法来处理夏时制。 基本上,每个国家/地区都可以自行决定DST的开始时间和结束时间。 作为开发人员,我们唯一能做的就是使用某种表进行查找。 大多数计算机语言都在语言中集成了这样的表格。

在Java中,可以使用TimeZone类的inDaylightTime方法。 如果您想知道DST在特定年份开始或结束的确切日期和时间,我建议使用Joda Time。 我看不出仅使用标准库就能找到答案的干净方法。

下面的程序是一个示例:(请注意,如果某个时区在某年没有DST,它可能会产生意外结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class App {
    public static void main(String[] args) {
        DateTimeZone dtz = DateTimeZone.forID("Europe/Amsterdam");

        System.out.println(startDST(dtz, 2008));
        System.out.println(endDST(dtz, 2008));
    }

    public static DateTime startDST(DateTimeZone zone, int year) {
        return new DateTime(zone.nextTransition(new DateTime(year, 1, 1, 0, 0, 0, 0, zone).getMillis()));
    }

    public static DateTime endDST(DateTimeZone zone, int year) {
        return new DateTime(zone.previousTransition(new DateTime(year + 1, 1, 1, 0, 0, 0, 0, zone).getMillis()));
    }
}

Richters的答案是正确的,应该接受。

正如Richters所指出的,夏令时(DST)或其他异常情况没有逻辑。政治家任意重新定义其时区中使用的UTC偏移量。他们做出这些改变的时候常常没有什么预警,甚至完全没有警告,就像朝鲜几周前所做的那样。

java.time

这里有一些进一步的想法,以及使用现代java.time类的示例代码,该类继他的Answer中显示的Joda-Time类之后。

ICANN维护的列表tzdata(以前称为Olson数据库)中跟踪了这些更改。您的Java实现,主机操作系统和数据库系统都可能拥有该数据的自己的副本,当更改为您关心的区域的模式时,必须根据需要替换这些副本。这些更改没有逻辑,因此无法以编程方式预测这些更改。您的代码必须调用tzdata的新副本。

So for example between the 25th and the 31th of October we have to check, if the actual date is a sunday, it is before or after 2 o'clock...

实际上,您无需确定转换点。一个好的日期时间库会自动为您处理。

Java具有最好的此类库,即业界领先的java.time类。当您要求某个地区(时区)中某个日期的日期时,如果该日期时间无效,则会自动进行调整。阅读ZonedDateTime的文档以了解该调整中使用的算法。

1
2
3
4
ZoneId z = ZoneId.of("America/Montreal" );
LocalDate ld = LocalDate.of( 2018 , Month.MARCH , 11 );  // 2018-03-11.
LocalTime lt = LocalTime.of( 2 , 0 );  // 2 AM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );

请注意,结果是3 AM,而不是请求的2 AM。该日期当天该区域没有凌晨2点。因此,java.time调整为凌晨3点,因为时钟"提前"了一个小时。

zdt.toString(): 2018-03-11T03:00-04:00[America/Montreal]

如果您需要研究为时区定义的规则,请使用ZoneRules类。

获取当前时刻使用的DST偏移量。

1
Duration d = z.getRules().getDaylightSavings?( Instant.now() ) ;

获取下一个计划的更改,以ZoneOffsetTransition对象表示。

1
2
3
ZoneId z = ZoneId.of("America/Montreal" );
ZoneOffsetTransition t = z.getRules().nextTransition( Instant.now() );
String output ="For zone:" + z +", on" + t.getDateTimeBefore() +" duration change:" + t.getDuration() +" to" + t.getDateTimeAfter();

For zone: America/Montreal, on 2018-11-04T02:00 duration change: PT-1H to 2018-11-04T01:00

continent/region格式指定正确的时区名称,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用3-4个字母的缩写,例如ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

  • Java SE 8,Java SE 9,Java SE 10和更高版本

    • 内置的
    • 标准Java API的一部分,具有捆绑的实现。
    • Java 9添加了一些次要功能和修复。
  • Java SE 6和Java SE 7

    • java.time的许多功能在ThreeTen-Backport中都被反向移植到Java 6和7。
  • 安卓系统

    • 更高版本的Android捆绑了java.time类的实现。
    • 对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP…。

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuarter等。


推荐阅读

    linux磁盘检测命令?

    linux磁盘检测命令?,情况,系统,数据,检测,管理,信息,命令,磁盘,设备,单位,lin

    硬盘检测命令linux?

    硬盘检测命令linux?,信息,情况,系统,管理,数据,检测,百分比,命令,工具,设备,l

    linux性能检测命令?

    linux性能检测命令?,系统,情况,信息,状态,工具,实时,百分比,指标,分析,命令,

    linux系统时钟命令?

    linux系统时钟命令?,时间,系统,命令,信息,城市,网上,资料,时区,终端,时分,lin

    linux命令解决方案?

    linux命令解决方案?,系统,管理,数据,电子,工作,电脑,软件,情况,不了,档案,lin

    linux修改时钟命令?

    linux修改时钟命令?,时间,系统,大陆,国家,时区,命令,信息,终端,时钟,日期,lin

    linux中日期相关命令?

    linux中日期相关命令?,时间,系统,信息,命令,代码,服务,工作,工具,终端,时分,l

    防篡改算法linux命令?

    防篡改算法linux命令?,技术,网络,系统,数据,区块链,电子,交易,信息,网站,国

    linux设日期时间命令?

    linux设日期时间命令?,时间,系统,命令,国家,环境,数据,电脑,标准,信息,大陆,l

    linux时钟同步命令?

    linux时钟同步命令?,时间,系统,服务,中国,地址,公共,管理,时钟,服务器,界面,

    linux系统改日期命令?

    linux系统改日期命令?,时间,系统,信息,命令,终端,时分,窗口,操作系统,一下

    linux检测硬件的命令?

    linux检测硬件的命令?,信息,系统,检测,工具,第一,数据,设备,分析,实时,百度,

    linux命令日期修改?

    linux命令日期修改?,时间,系统,电脑,信息,命令,标准,文件,终端,日期,时分,LIN

    linux命令超时检测?

    linux命令超时检测?,时间,网络,检测,系统,地址,状态,电脑,代码,软件,设备,lin

    linux切换日期命令?

    linux切换日期命令?,时间,系统,信息,命令,城市,终端,时分,日期,窗口,操作系

    linux设置日期命令?

    linux设置日期命令?,时间,系统,标准,命令,信息,大陆,国家,日期,时钟,时区,详

    linux设置时钟命令?

    linux设置时钟命令?,时间,系统,服务,图片,命令,网络,信息,风险,国家,大陆,lin

    linux下端口检测命令?

    linux下端口检测命令?,检测,系统,状态,工具,情况,端口,网络,服务,灵活,信息,l

    linux修改日期命令?

    linux修改日期命令?,时间,系统,命令,信息,工具,工作,服务,代码,日期,终端,lin

    linux检测摄像头命令?

    linux检测摄像头命令?,系统,工具,情况,实时,信息,状态,平均,设备,检测,数据,L