当前位置: 首页 > 知识库问答 >
问题:

1小时时差夏令时问题

景承教
2023-03-14
public static String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
    String strLocalTime = null;
    try {
        SimpleDateFormat sdf = getSimpleDateFormat(dateFormat, whichTimeZone);
        Date date = sdf.parse(strTime);

        AppLog.e(TAG,"Timezone = " + whichTimeZone);
        AppLog.e(TAG,"Date = " + strTime);
        AppLog.e(TAG,"Date in CET = " + date.toString());
        AppLog.e(TAG,"inDaylightTime = " + sdf.getTimeZone().inDaylightTime(date));
        AppLog.e(TAG,"DST savings = " + sdf.getTimeZone().getDSTSavings());

        if (sdf.getTimeZone().getDSTSavings() == 3600000) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.HOUR, 1);
            Date oneHourBack = cal.getTime();

            SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
            strLocalTime = local.format(oneHourBack);
        } else {
            SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
            strLocalTime = local.format(date);
        }
    } catch (ParseException e) {
        AppLog.e(TAG, e.getMessage(), e);
    }

    AppLog.e(TAG,"Local Time = " + strLocalTime);
    return strLocalTime;
}
private static SimpleDateFormat getSimpleDateFormat(String format, String tz) {
        TimeZone timeZone = TimeZone.getTimeZone(tz);
        timeZone.useDaylightTime();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.getDefault());
        simpleDateFormat.setTimeZone(timeZone);
        return simpleDateFormat;
    }

函数获取用于本地设备转换的简单日期格式:

/**
     * @param format
     * @return
     */
    private static SimpleDateFormat getLocalSimpleDateFormat(String format) {
        TimeZone timeZone = TimeZone.getDefault();
        timeZone.useDaylightTime();

        SimpleDateFormat localSdf = new SimpleDateFormat(format, Locale.getDefault());
        localSdf.setTimeZone(timeZone);
        return localSdf;
    }

产出:

日期=2018-04-22 14:30

上面的示例是基于伦敦时区的,而当我们在IST时区中尝试时,它返回的是正确的时间。

我们通过检查时区的indaylighttime函数来处理不同的DST时间,但它不起作用。

我肯定与夏令时有关,但我不明白。谢谢你的帮助?

共有1个答案

姬俊能
2023-03-14

首先,您使用的是旧的、过时的日期和时间类:SimpleDateFormatdateCalendarTimeZone。它们以设计糟糕而闻名,有时使用起来很麻烦。我的第一个建议是使用现代Java日期和时间APIJava.time重写代码。它的错误少得多,我希望您能更容易地开发正确的代码。

也就是说,不管你使用的是老式的还是现代的课程,都不要自己处理暑假。图书馆类会为你做这件事。你的工作是使时区正确。不要增加或减少一个小时来补偿夏天的时间。看看其他关于从一个时区转换到另一个时区的问题,有很多。

不要使用三个或四个字母的时区缩写。CET不是一个时区。IST是模棱两可的,它可能意味着爱尔兰夏令时、以色列标准时间或印度标准时间。欧洲冬季使用CET的国家从2018年3月26日开始使用CET(中欧夏令时)。

还要确保将您的设备时区设置为真正的时区。似乎您已经将其设置为GMT+01:00,这是GMT偏移量,而不是时区。它同意欧洲/伦敦时区和冬季CET,但不是在3月26日之后。

最后,将1小时添加到日历中,将日历向前翻转1小时,然后调用从中获得的日期OneHourback。这看起来不对。您的意思是减去1小时,还是变量应该是OneHourForward

编辑:我可能还没有确切地理解哪些时区对您来说是正确的,因此也不知道代码的正确输出是什么。所以,把下面这些仅仅作为你想要完成的事情的一个猜测。请填写正确的时区。

public static String convertIntoLocalTime(
        String strTime, String serverTimeZone, String dateFormat) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
    ZonedDateTime serverDateTime = LocalDateTime.parse(strTime, formatter)
            .atZone(ZoneId.of(serverTimeZone));

    AppLog.e(TAG, "Server timezone = " + serverTimeZone);
    AppLog.e(TAG, "Date = " + strTime);
    AppLog.e(TAG, "Date in server timezone = " + serverDateTime.toString());

    ZonedDateTime deviceTime = serverDateTime
            .withZoneSameInstant(ZoneId.systemDefault());
    String strLocalTime = deviceTime.format(formatter);

    AppLog.e(TAG, "Device Time = " + deviceTime);
    AppLog.e(TAG, "Local Time = " + strLocalTime);

    return strLocalTime;
}
    convertIntoLocalTime("2018-04-22 14:30", "Europe/Berlin", "yyyy-MM-dd HH:mm")
Server timezone = Europe/Berlin
Date = 2018-04-22 14:30
Date in server timezone = 2018-04-22T14:30+02:00[Europe/Berlin]
Device Time = 2018-04-22T13:30+01:00[Europe/London]
Local Time = 2018-04-22 13:30

是的,java.time在较旧和较新的Android设备上都能很好地工作。它只需要至少Java6。

  • 在Java8及更高版本中,以及在较新的Android设备上(据我所知,从API级别26开始),现代API是内置的。
  • 在Java6和7中获得ThreeTen Backport,即新类的Backport(ThreeTen for JSR310;参见底部的链接)。
  • 在(旧的)Android上使用ThreeTen Backport的Android版。叫做threetenabp。并确保通过子包从org.threeten.bp导入date和time类。
  • tz数据库时区列表
  • Oraclehtml" target="_blank">教程:解释如何使用java.Time.
  • 的日期时间
  • Java规范请求(JSR)310,其中首次描述了java.time
  • ThreeTen Backport项目,Java.time到Java 6和7的Backport(ThreeTen for JSR-310).
  • Threetenabp,ThreeTen backport的Android版
  • 问题:如何在Android项目中使用ThreeTenABP,并给出了非常透彻的解释。
 类似资料:
  • 轻触方格启用设定,即可将夏令时反映于时间显示中。

  • 问题内容: 如何检查夏令时是否有效? 问题答案: 您可以使用并查看返回值中的标志。 使用,您可以在任意时间问相同的问题,以了解DST在当前时区是否有效。

  • 夏令时间 选择[标准]或[夏令时间]。

  • 问题内容: 我正在编写一个处理很多时区并跨越时区的程序。我最常处理的两件事是从“ now”创建一个datetime对象,然后本地化一个朴素的datetime对象。 要从现在开始在太平洋时区创建datetime对象,我目前正在执行此操作(python 2.7.2+) 关于DST,这是否正确?如果没有,我想应该这样做: 我的问题是为什么?谁能告诉我第一个错误而第二个秒正确的情况? 至于我的秒数问题,假

  • 约旦有夏令时...是,还是不?? 谢了!

  • 我的API使用ISO 8601向客户表示时间。我们有一个功能,我们希望显示它来自哪个时区。通过纯粹存储时区偏移,我们失去了对该细节的跟踪。 即,犹他州和亚利桑那州在一年中的一半时间遵守MST,犹他州在另一半时间切换到MDT。我们目前的解决方案是确定日期是否在夏令时,并在夏令时使用时区,否则使用,但亚利桑那州的ISO 8601日期将导致太平洋夏令时。 有没有办法指定是否以ISO 8601格式观察夏令