java / android中的时区说明

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

我有下面的代码

public Long getEpochTime(String dateToGetItsEpoch) throws ParseException
{
    TimeZone timeZone = TimeZone.getTimeZone("UTC");
    final String REQUEST_DATE_FORMAT = "dd/MM/yyyy h:m";

    DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
    Date localDate = format.parse(dateToGetItsEpoch);

    Calendar cal = Calendar.getInstance(timeZone);
    cal.setTime(localDate);

    format.setTimeZone(timeZone);
    final String utcTime = format.format(cal.getTime());

    Date d = cal.getTime();

    return d.getTime();
}

如果我将设备的语言环境更改为其他语言,则总是以UTC时间作为返回值。哪个是正确的,但是我想知道这是怎么回事?设备如何知道我给它的日期是哪个时区,以便它相应地进行计算?

android date datetime timezone locale
2个回答
3
投票

A Date根本没有时区。默认情况下,SimpleDateFormat用于解析和格式化。 Calendar也是如此; Date没有。

给出以下操作顺序:

TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(dateToGetItsEpoch);

Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);

format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());

......最初是使用设备的默认时区parsing字符串,然后以UTC formatting字符串。请注意,Calendar部分与此处无关-您将获得与以下相同的结果:

TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date date = format.parse(dateToGetItsEpoch);
format.setTimeZone(timeZone);
final String utcTime = format.format(date);

我个人建议在Java中使用Joda Time进行日期/时间工作,请注意。它是一个比Calendar / Date更干净的API。


0
投票

java.time

Answer by Jon Skeet是正确的。这是一些更新的代码,以使用现代的[[java.time类取代了麻烦的旧式日期时间类。

格式化模式

定义格式以匹配您的输入。

顺便说一下,您的格式选择不佳。相反,我建议使用设计用于交换日期时间值作为文本的标准ISO 8601格式。

12小时与24小时制

您的输入数据或格式模式有缺陷。您使用的小写字母h表示12小时制(而不是24小时制,即大写的HHH)表示一个小时的一两位数字。因此,除非添加AMPM的指示符,否则您的输入没有任何意义。我会假设您错误地从您的问题的代码中忽略了这一点。

Locale locale = Locale.US ; DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu h:m a" ).withLocale( locale ) ;

LocalDateTime

将诸如LocalDateTime对象的字符串解析,因为它们缺少预期时区或UTC偏移量的指示符。

String input = "23/01/2020 4:5 PM" ; LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

ldt.toString():2020-01-23T16:05

片刻

我们上面获得的LocalDateTime对象确实

不是表示时刻,不是时间轴上的点。我们23号的时间大约是下午4点。但是我们不知道这是否意味着在东京,图卢兹或托莱多是下午4点-所有这些时刻都相差几个小时。

要确定时刻,我们必须在一定程度上知道预期的时区。然后将该区域用作ZoneId以得到ZonedDateTime。然后我们到了片刻。

Locale不是时区

我的设备的语言环境到任何地方

A

Locale具有nothing到时区

Locale用于对表示日期时间对象的生成文本进行本地化。 要本地化,请指定:

    [FormatStyle确定字符串应该是多长或缩写。
  • FormatStyle确定:
    • 用于翻译日名,月名等的
    • 人类语言
    • 。>[[文化规范决定缩写,大写,标点,分隔符等问题。
  • 示例:
  • Locale

    [您可能有魁北克省的工程师使用Locale来制定人类语言和文化规范,但是在日本访问时使用Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc. DateTimeFormatter f = DateTimeFormatter .ofLocalizedDateTime( FormatStyle.FULL ) .withLocale( l ) ; String output = myZonedDateTime.format( f ); 时区来安排约会。

    Locale.CANADA_FRENCH

    返回到您的Asia/Tokyo对象。如果您确定要代表突尼斯的挂钟时间,请使用ZonedDateTime时区。

    LocalDateTime

    您问:

    设备如何知道我给它的日期是哪个时区,以便它相应地进行计算?

    您正在使用可怕的日期时间类,而这些类却无法说明缺乏时区或UTC偏移量指示符的日期时间概念。因此,从技术上讲,在

    Joda-Time

    及其后继者

    java.time

    之前的那几天,您的代码是一团糟,无法破解的事情。
    我建议花no努力尝试理解Africa/TunisZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt = ldt.atZone( z ) ; 的行为。只需继续使用

    java.time

    ,这是业界领先的日期时间处理框架。
    © www.soinside.com 2019 - 2024. All rights reserved.