【问题标题】:Save time with another time zone diiferent from server time zone使用不同于服务器时区的另一个时区节省时间
【发布时间】:2021-09-09 17:08:40
【问题描述】:

我选择了一个时间,例如我输入了 Thu Jan 01 16:00:00 WET 1970 以及一个时区,例如 GMT+1:00。我的意思是我想用这个时区记录这个日期(gmt+1 已经是 16:00)。但在保存模型后,该值将在数据库中保存为 Thu Jan 01 15:00:00 WET 1970。

服务器位于非洲/卡萨布兰卡时区。

我尝试将此日期转换为我想要的带有时区的字符串,它显示了正确的时间,但是当我尝试将此字符串转换为日期时,我仍然收到少一小时的时间。

      DisplayedTimeZone displayedTimeZone = configuration.getDisplayedTimeZone();
    if(displayedTimeZone != null){
        Date orderCuttOffTime = configuration.getCutOffTime(); // Thu Jan 01 15:00:00 WET 1970
        if(orderCuttOffTime != null){
          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
          sdf.setTimeZone(TimeZone.getTimeZone(displayedTimeZone.getCode()));
          String closingTime = sdf.format(orderCuttOffTime); // 1970-01-01 16:00:00 +0100
          try {
                configuration.setCutOffTime(dateFormat.parse(cuttOffTime)); // returns again Thu Jan 01 15:00:00 WET 1970 and not 16:00:00
          }catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }

甚至 cuttofftime 包含我想保存在数据库中的时间 Thu 1970-01-01 16:00:00 +0100 dateFormat.parse(cuttOffTime) 返回值 Thu Jan 01 15:00:00 WET 1970

我想在解析期间向我发送一个与字符串中相同时间的日期

【问题讨论】:

    标签: java date time timezone


    【解决方案1】:

    java.util.Date 对象仅表示时间轴上的一个瞬间 — 自 UNIX 纪元(格林威治标准时间 1970 年 1 月 1 日 00:00:00)以来的毫秒数的包装。由于它不保存任何时区信息,它的 toString 函数应用 JVM 的时区以返回格式为 EEE MMM dd HH:mm:ss zzz yyyyString,从这个 毫秒 值。要以不同的格式和时区获取java.util.Date 对象的String 表示,您需要使用具有所需格式和适用时区的SimpleDateFormat,例如

    Date date = new Date();
    
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
    
    sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
    String strDateNewYork = sdf.format(date);
    
    sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
    String strDateUtc = sdf.format(date);
    

    java.time

    随着 2014 年 3 月 Java SE 8 的发布,过时且容易出错的旧版 Date-Time API(java.util Date-Time 类型及其格式类型,SimpleDateFormat 等)被 java.time 取代,现代日期时间 API*following table 描述了 ANSI SQL 类型与 java.time 类型的映射:

    ANSI SQL Java SE 8
    DATE LocalDate
    TIME LocalTime
    TIMESTAMP LocalDateTime
    TIME WITH TIMEZONE OffsetTime
    TIMESTAMP WITH TIMEZONE OffsetDateTime

    请注意,任何 JDBC 驱动程序都不支持 ZonedDateTimeInstant,而某些驱动程序例如PostgreSQL也不支持OffsetTime/TIME [ WITHOUT TIMEZONE ]

    如何在JDBC中使用?

    下面是一个示例代码,用于将 UTC 中的当前 OffsetDateTime 插入到 columnfooTIMESTAMP WITH TIMEZONE 类型)中:

    OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
    PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
    st.setObject(1, odt);
    st.executeUpdate();
    st.close();
    

    下面是从columnfoo 检索OffsetDateTime 的示例代码:

    Statement st = conn.createStatement();
    ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
    while (rs.next()) {
        // Assuming the column index of columnfoo is 1
        OffsetDateTime odt = rs.getObject(1, OffsetDateTime.class));
        System.out.println(odt);
    }
    rs.close();
    st.close();
    

    以防万一您需要转换 odt 以表示您所在时区的日期时间:

    ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("Africa/Casablanca"));
    System.out.println(zdt); // With timezone and timezone offset
    System.out.println(zdt.toOffsetDateTime()); // With timezone offset
    

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。


    * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      【解决方案2】:

      鉴于cutOffTimejava.util.Date,您无能为力,因为Date 没有时区并且始终以UTC 存储。

      您看到的WET 时区只是Date 值的默认呈现。

      如果您想保存带时区但不带日期的时间,请使用 Java 8+ OffsetTime 类而不是 Date

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-10
        • 2015-09-01
        • 2014-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        相关资源
        最近更新 更多