如何在 android 中将日期从 GMT 时区解析为 IST 时区和反之亦然

Posted

技术标签:

【中文标题】如何在 android 中将日期从 GMT 时区解析为 IST 时区和反之亦然【英文标题】:How to Parse Date from GMT TimeZone to IST TimeZone and Vice Versa in android 【发布时间】:2012-12-28 04:13:00 【问题描述】:

我正在开发一个项目,该项目从IST(印度标准时间)的后端获取日期/时间,如"2013-01-09T19:32:49.103+05:30" 所示。但是,当我使用以下 DateFormat 解析它时

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

接着解析..

Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");


System.out.println("XYZ ==============>"+date);

它以 GMT 格式显示日期作为输出,即

Wed Jan 09 14:02:49 GMT+00:00 2013.

我已经尝试使用 TimeZone 类作为..

TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);

但没有效果..

我怎样才能得到一个Date 类对象,其日期为IST 格式而不是格林威治标准时间...

请提供适当的解决方案..

编辑:

这就是代码的样子:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

TimeZone timeZone=TimeZone.getTimeZone("IST");
sdf.setTimeZone(timeZone);

Date date = sdf.parse("2013-01-09T19:32:49.103+05:30");
String formattedDate=sdf.format(date);

System.out.println("XYZ ==============>"+formattedDate);

【问题讨论】:

日期类没有指定的时区格式。 【参考方案1】:

tl;博士

OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" )  // Parsed.
              .toInstant()                               // Adjusted to UTC.

见live code in IdeOne.com。

ISO 8601

2013-01-09T19:32:49.103+05:30 的输入字符串恰好是标准 ISO 8601 格式。末尾的+05:30 表示提前五个半小时的offset-from-UTC,用于印度。

java.time

您正在使用麻烦的旧日期时间类,现在是遗留的,被 java.time 类取代。

在解析/生成表示日期时间值的字符串时,java.time 类默认使用 ISO 8601 格式。所以根本不需要指定格式模式。

由于您的输入代表时间轴上与 UTC 有偏移的时刻,我们将其解析为 OffsetDateTime 对象。

OffsetDateTime odt = OffsetDateTime.parse( "2013-01-09T19:32:49.103+05:30" );

odt.toString(): 2013-01-09T19:32:49.103+05:30

要获取UTC 值中的简单对象,请提取Instant。这个Instant 类是java.time 的基本构建块类。 Instant 类代表UTC 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

您可以将OffsetDateTime 视为Instant 加上ZoneOffset

Instant instant = odt.toInstant();  // UTC.

调用toString 时,会以标准ISO 8601 格式生成String 对象。末尾的ZZulu 的缩写,表示UTC。

instant.toString(): 2013-01-09T14:02:49.103Z

Instant 在各种方面受到限制,例如在生成各种格式的字符串时。因此,您可能希望将OffsetDateTime 调整为UTC 作为其偏移量;换句话说,零偏移量。 ZoneOffset 类包含一个 UTC 常量 ZoneOffset.UTC

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );

您还可以对Instant 应用偏移量(或时区)。致电atOffsetatZone

Instant 类是 java.time 的基本构建块类。可能经常在您的代码中使用,因为最佳实践是在 UTC 中完成大部分工作。

OffsetDateTime odt = instant.atOffset( ZoneOffset.ofHoursMinutes( 5 , 30 ) );

时区

请注意,与 UTC 的偏移不是时区。时区是一个偏移量加上一组规则,过去和现在,用于处理异常,例如Daylight Saving Time (DST)。因此,如果您确实确定正确的时区,则时区总是比仅仅偏移更可取。

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

如果您知道预期的时区,请应用 ZoneId 以获取 ZonedDateTime 对象。但千万不要假设没有验证输入数据的来源。许多不同的区域可能共享一个特定的偏移量。例如,在我们在这里输入的情况下,偏移量 +05:30 今天恰好在印度 (Asia/Kolkata) 和斯里兰卡 (Asia/Colombo) 中使用。对于过去、现在或未来的不同异常,这两个时区可能有不同的规则。

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

ZonedDateTimetoString 方法以一种明智的方式扩展了标准 ISO 8601 格式,方法是在方括号中附加时区名称。在这种情况下,[Asia/Kolkata]

zdt.toString(): 2013-01-09T19:32:49.103+05:30[亚洲/加尔各答]


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

从哪里获得 java.time 类?

Java SE 8SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6SE 7 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android ThreeTenABP 项目专门针对 android 改编 ThreeTen-Backport(如上所述)。 见How to use…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

【参考方案2】:

您可以简单地通过使用 Calender 类来做到这一点。请检查下面的sn-ps:

Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(<--time stamp-->);
//calendar.setTime(<--date object of gmt date-->); 
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy 'at' hh:mm a");
sdf.setTimeZone(TimeZone.getDefault());
String result=sdf.format(calendar.getTime()); 

【讨论】:

【参考方案3】:

日期没有任何时区。它只是自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数的持有者。采用您用于解析的相同 DateFormat,设置 IST 时区并格式化您的日期,如下例所示

    DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    Date date = sdf.parse("2013-01-09T19:32:49.103+05:30"); 
    sdf.setTimeZone(TimeZone.getTimeZone("IST"));
    System.out.println(sdf.format(date));

输出

2013-01-09T19:32:49.103+05:30

请注意,自 1.7 起,XXX 模式用于 ISO 8601 时区 (-08:00)。如果您使用的是 1.6,请尝试 Z。有关格式模式的详细信息,请参阅 SimpleDateFormat API

【讨论】:

@Evgniy XXX 代表什么,因为代码正在抛出 Exception..Unknown Pattern Exception 'X' 从1.7开始如果你不是1.7试试ZZZ @Evgniy 如果我不在 SimpleDateFormat 构造函数中提及 ZZZ,它对我有用..thanx 很多../ 但是如果我写zzz,输出仍然是GMT,如图所示:2013-01-09T14:02:49.103+0000 查看 SimpleDateFormat API z 和 Z 是不同的模式【参考方案4】:

我怎样才能得到一个日期类对象,它的日期是 IST 格式而不是 GMT...

你不能。 Date 没有格式时区。它仅表示自 1970 年 1 月 1 日 UTC 午夜的 Unix 纪元以来的毫秒数。相反,Date.toString()总是使用默认时区。

要使用特定格式和时区,请使用DateFormat 而不是Date.toString()。您可以使用DateFormat.setTimeZone() 设置时区,然后使用DateFormat.format()Date 转换为StringDateFormat 本身有一些工厂方法用于创建,或者如果你想指定一个特定的模式,你可以使用SimpleDateFormat

正如 Abu 所说,Joda Time 比内置 API 更好的日期/时间 API,尽管标准库只是格式化日期/时间并没有做坏事.请注意,DateFormat 及其子类通常不是线程安全的。

【讨论】:

@NarendraPal:为什么要更改默认时区?为什么要创建一个具有相同值的新Date?也不清楚您要实现什么目标或您提供的代码将做什么。 我无法详细说明我的问题,但你可以看看这个。 ***.com/a/10545852/1395259 @NarendraPal:你甚至没有稍微解释你的问题,更不用说详细解释了。您在现已删除的评论中倾倒了一堆代码(使我的评论看起来很奇怪),却没有提供任何关于您要实现的目标的线索。您提供的链接并没有让我们更多地了解您要做什么,或者为什么它与我的回答有关。听起来您应该在tinyurl.com/so-list 之后提出一个新问题(为什么您能够提供您想要实现的目标的详细信息?“我想转换时区 X 的日期/时间"...) 因为我尝试过 DateFormat.format() 但它返回的字符串具有 GMT 格式的时间。 @AmritpalSingh:您是否按照我的回答将时区设置为您想要使用的时区?

以上是关于如何在 android 中将日期从 GMT 时区解析为 IST 时区和反之亦然的主要内容,如果未能解决你的问题,请参考以下文章

从 GMT 值计算时区 - Android

如何将日期/时间从 GMT 转换为本地时区

需要在 oracle 中将任何时区转换为 GMT 时区

如何在 Python 中将本地时间转换为 GMT 时区

如何使用 MQ 的 esql 将日期的特定时区转换为 GMT 时区?

如何在 Python 中获取或打印 GMT 时区的当前日期时间? [复制]