如何在 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
对象。末尾的Z
是Zulu
的缩写,表示UTC。
instant.toString(): 2013-01-09T14:02:49.103Z
Instant
在各种方面受到限制,例如在生成各种格式的字符串时。因此,您可能希望将OffsetDateTime
调整为UTC 作为其偏移量;换句话说,零偏移量。 ZoneOffset
类包含一个 UTC 常量 ZoneOffset.UTC
。
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );
您还可以对Instant
应用偏移量(或时区)。致电atOffset
或atZone
。
Instant
类是 java.time 的基本构建块类。可能经常在您的代码中使用,因为最佳实践是在 UTC 中完成大部分工作。
OffsetDateTime odt = instant.atOffset( ZoneOffset.ofHoursMinutes( 5 , 30 ) );
时区
请注意,与 UTC 的偏移不是时区。时区是一个偏移量加上一组规则,过去和现在,用于处理异常,例如Daylight Saving Time (DST)。因此,如果您确实确定正确的时区,则时区总是比仅仅偏移更可取。
以continent/region
的格式指定proper time zone name,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
如果您知道预期的时区,请应用 ZoneId
以获取 ZonedDateTime
对象。但千万不要假设没有验证输入数据的来源。许多不同的区域可能共享一个特定的偏移量。例如,在我们在这里输入的情况下,偏移量 +05:30
今天恰好在印度 (Asia/Kolkata
) 和斯里兰卡 (Asia/Colombo
) 中使用。对于过去、现在或未来的不同异常,这两个时区可能有不同的规则。
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
ZonedDateTime
的 toString
方法以一种明智的方式扩展了标准 ISO 8601 格式,方法是在方括号中附加时区名称。在这种情况下,[Asia/Kolkata]
。
zdt.toString(): 2013-01-09T19:32:49.103+05:30[亚洲/加尔各答]
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
Java SE 8 和 SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 SE 7 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android ThreeTenABP 项目专门针对 android 改编 ThreeTen-Backport(如上所述)。 见How to use…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和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 起,XX
X 模式用于 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
转换为String
。 DateFormat
本身有一些工厂方法用于创建,或者如果你想指定一个特定的模式,你可以使用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 时区和反之亦然的主要内容,如果未能解决你的问题,请参考以下文章