gpt4 book ai didi

Android 和 iOS 库的行为就像 1996 年之前从未有过夏令时一样

转载 作者:行者123 更新时间:2023-11-29 11:41:13 26 4
gpt4 key购买 nike

行话:

CET : Central European Time.
Daylight saving time : UTC+1 in winter, UTC+2 in summer.

在 CET 地区,Android 和 iOS 库的行为就像 1996 年之前从未有过夏令时一样,而 .Net 的行为则一直存在。

为了说明这种行为,这里有一些在 CET 机器上执行的用 .NET/Java 编写的代码。

在 .Net 中:

static void PrintDate(String input)
{
String format = "yyyy-MM-ddTHH:mm:ss.fffffffzzz";
var date = DateTime.ParseExact(input, format, CultureInfo.InvariantCulture);
var output = date.ToString(format, CultureInfo.InvariantCulture);
System.Diagnostics.Debug.WriteLine(input + " => " + output);
}

在 Android 和 iOS 中(只是 java 示例,但两者的行为方式相同)。

static void printDate(String input)
{
String format = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZZZZZ";
Date date = new SimpleDateFormat(format).parse(input);
String output = new SimpleDateFormat(format).format(date);
Log.i("MyTag", input + " => " + output);
}

对该方法的简单调用:

public static void Main()
{
PrintDate("1993-10-06T00:00:00.0000000+02:00");
PrintDate("1993-12-06T00:00:00.0000000+02:00");
PrintDate("1996-10-06T00:00:00.0000000+02:00");
PrintDate("1996-12-06T00:00:00.0000000+02:00");
}

这是 .Net 中的输出:

1993-10-06T00:00:00.0000000+02:00 => 1993-10-06T00:00:00.0000000+02:00
1993-12-06T00:00:00.0000000+02:00 => 1993-12-05T23:00:00.0000000+01:00
1996-10-06T00:00:00.0000000+02:00 => 1996-10-06T00:00:00.0000000+02:00
1996-12-06T00:00:00.0000000+02:00 => 1996-12-05T23:00:00.0000000+01:00

这是 Android/iOs 中的输出

1993-10-06T00:00:00.0000000+02:00 => 1993-10-05T23:00:00.0000000+01:00
1993-12-06T00:00:00.0000000+02:00 => 1993-12-05T23:00:00.0000000+01:00
1996-10-06T00:00:00.0000000+02:00 => 1996-10-06T00:00:00.0000000+02:00
1996-12-06T00:00:00.0000000+02:00 => 1996-12-05T23:00:00.0000000+01:00

我怎样才能使这三种平台形式之间的行为同质化?

最佳答案

在 Java 中,SimpleDateFormat 使用 JVM 默认时区(如果您未在其中设置时区)。 (用 TimeZone.getDefault() 检查你的是什么)。

所以 1993-10-06T00:00+02:00 被转换为 1993-10-05T23:00+01:00 可能是因为默认时区是一个1993 年 10 月有 +01:00 偏移,而 1996 年 10 月是夏令时 (+02:00)。我猜是 Europe/Paris,但也可以是其他的,如 lots of timezones uses CET as a short name .

无论如何,只要查看DST in Paris的历史记录即可。请注意,1993 年 10 月的偏移量是 +01:00,而 1996 年 10 月 6 日th 的偏移量是 +02:00。所以这是一个很好的猜测,但具有相同规则的任何时区都会有相同的行为。

另外,+02:00an offset, not a timezone .只是 +02:00 并不一定意味着它在 DST 期间是 CET,因为 there's more than one timezone that uses this offset .像 CET 这样的短名称是 ambiguous and not standard , 所以你应该考虑使用 IANA timezones names (始终采用地区/城市格式,如 America/Sao_PauloEurope/Paris)。

无论如何,如果你不想有可变的偏移量,你不应该依赖 JVM 默认时区,因为它可以有 DST 效果并且偏移量会根据日期(和默认时区 can be changed without notice, even at runtime ).避免它的一种方法是在格式化程序中设置固定的偏移量:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZZZZZ");
// set the offset +02:00, so all dates will be formatted using this
// (instead of the current offset for the JVM default timezone)
sdf.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
Date date = sdf.parse("1993-10-06T00:00:00.0000000+02:00");
System.out.println(sdf.format(date));

只是一些简短的笔记:

  • SimpleDateFormat 不适用于小数点后超过 3 位的情况。在上面的例子中,它工作得很好,因为它全是零,但如果你有任何不同于零和超过 3 位数字的值,你可以有 strange, wrong, unexpected results .在这种情况下,您应该删除多余的数字,因为此类根本无法处理超过 3 个数字(而且它也不能很好地格式化)。
  • 我正在使用 JDK 7 进行测试,因此模式 ZZZZZ 不适用于解析。相反,我使用了 yyyy-MM-dd'T'HH:mm:ss.SSSSSSSXXX,它解析上面的输入,并将日期格式化为 1993-10-06T00:00 :00.0000000+02:00(但请注意 X 在 JDK 6 中不可用)
  • 如果您想要另一个偏移量的输出,只需在 getTimeZone 方法中相应地更改它。如果您想要 UTC,请使用 getTimeZone("UTC")

Java 新日期/时间 API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues ,并且它们正在被新的 API 取代。

在 Android 中,您可以使用 ThreeTen Backport ,Java 8 的新日期/时间类的一个很好的反向移植。要使其正常工作,您还需要 ThreeTenABP (更多关于如何使用它的信息 here)。

这个新 API 的一项改进是支持纳秒(小数点后最多 9 位),因此它可以处理您的输入而不会出现 SimpleDateFormat 的问题。

这个新 API 也有 lots of new date/time types适合不同的情况。在这种情况下,您有一个特定偏移量的日期和时间,并希望维护它。所以,最好的类是 org.threeten.bp.OffsetDateTime:

OffsetDateTime odt = OffsetDateTime.parse("1993-10-06T00:00:00.0000000+02:00");
System.out.println(odt.toString()); // 1993-10-06T00:00+02:00

请注意,如果秒和纳秒为零,则 toString() 方法会忽略它们。如果您希望输出与输入完全相同(小数点后有 7 位),只需创建一个 org.threeten.bp.format.DateTimeFormatter:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSXXX");
System.out.println(fmt.format(odt)); // 1993-10-06T00:00:00.0000000+02:00

要将其更改为另一个偏移量(或 UTC),请使用 org.threeten.bp.ZoneOffset:

// convert to UTC
odt = odt.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(fmt.format(odt)); // 1993-10-05T22:00:00.0000000Z

// convert to another offset (+01:00)
odt = odt.withOffsetSameInstant(ZoneOffset.ofHours(1));
System.out.println(fmt.format(odt)); // 1993-10-05T23:00:00.0000000+01:00

关于Android 和 iOS 库的行为就像 1996 年之前从未有过夏令时一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46453208/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com