为什么我无法获取时区“欧洲/阿姆斯特丹”中日期“1914-11-08 00:00:00”的时间戳?

问题描述 投票:0回答:1

最近我将 mysql-connector 从 5.1.47 升级到 8.0.33。之后,我遇到了一个错误:

Caused by: java.sql.SQLException: HOUR_OF_DAY: 0 -> 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:98) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:90) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:64) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:74) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:85) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.result.ResultSetImpl.getTimestamp(ResultSetImpl.java:947) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.mysql.cj.jdbc.result.ResultSetImpl.getTimestamp(ResultSetImpl.java:985) ~[mysql-connector-j-8.0.33.jar:8.0.33]
    at com.zaxxer.hikari.pool.HikariProxyResultSet.getTimestamp(HikariProxyResultSet.java) ~[HikariCP-4.0.3.jar:na]
    at org.hibernate.type.descriptor.sql.TimestampTypeDescriptor$2.doExtract(TimestampTypeDescriptor.java:84) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3214) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.persister.entity.Loadable.hydrate(Loadable.java:94) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.loadFromResultSet(EntityReferenceInitializerImpl.java:342) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    ... 113 common frames omitted

通过调查此错误,我发现新的 mysql 驱动程序会进行一些转换,并且我的数据集包含日期“1916-05-01 00:00 00”。根据维基百科,第一个全国范围内的夏令时实施是由德意志帝国和奥匈帝国实施的,两者都从 1916 年 4 月 30 日开始。所以它可能认为它无法转换 '1916-05-01 00:00从“1916-05-01 00:00 00”开始的时间戳“00”是“不存在”,只有“1916-05-01 01:00 00”。 我决定找出“欧洲/阿姆斯特丹”时区中所有这些“不存在”的日期。这是我的做法:

public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        start.setTime(sdf.parse("1900-01-01"));
        end.setTime(sdf.parse("2025-01-01"));
        List<String> errorItems = new ArrayList<>();
        while (!start.after(end)) {
            try {
                Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Europe/Amsterdam"), Locale.US);
                calendar.setLenient(false);
                calendar.set(start.get(Calendar.YEAR), start.get(Calendar.MONTH), start.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
                Timestamp ts = new Timestamp(calendar.getTimeInMillis());
                System.out.println(ts);
            } catch (IllegalArgumentException e) {
                errorItems.add(sdf.format(start.getTime()));
            }
            start.add(Calendar.DAY_OF_YEAR, 1);
        }
        System.out.println("error date: " + errorItems);
    }

结果是:[1914-11-08, 1916-05-01]

“1916-05-01”我已经理解了,但为什么是“1914-11-08”呢? 1914 年 DST 甚至还不存在。有人知道吗?

我想知道为什么我无法获取时区“欧洲/阿姆斯特丹”中日期“1914-11-08 00:00:00”的时间戳。

java mysql timezone mysql-connector dst
1个回答
0
投票

大约两年前,IANA 时区数据库的维护者决定,由于布鲁塞尔和阿姆斯特丹从 1970 年开始具有相同的时区规则,因此他们将“链接”欧洲/阿姆斯特丹与欧洲/布鲁塞尔。这有效地消除了 1970 年之前欧洲/阿姆斯特丹时区规则的历史,并替代了 1970 年之前欧洲/布鲁塞尔的时区规则。

对于欧洲/布鲁塞尔,当地时间 1914-11-08 00:00:00 不存在,因为当时当地时间提前一小时到达 1914-11-08 01:00:00。这一变化不适用于阿姆斯特丹。

您从 5.1.47 升级到 8.0.33 显然在 IANA tz 数据库中发现了这一变化。


PS:如果您不喜欢 IANA tz 数据库的这一更改,请不要迁怒于我。我只是一个使者。

© www.soinside.com 2019 - 2024. All rights reserved.