面对Android中的DateFormat问题,CDT转换为IST

时间:2016-05-09 15:59:27

标签: java android

我从Android手机获得的时间是

“Mon May 9 09:34:13 CDT 2016 \ r \ n \ r \ n”但在使用日期格式SimpleDateFormat(“EEE MMM dd HH:mm:ss zzz yyyy”,Locale.US)解析相同日期之后;

解析后给我一个日期

“Mon May 09 20:04:56 IST 2016”。

它清楚地表明小时数增加了11个小时。

如何解决这个问题,有人可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

不要忘记日期类是一个完全没有格式的类....

如果你想打印一个日期,你需要使用你创建的对象的格式方法......

例如:

public static void main(String[] args) throws ParseException {
    String myDate = "Mon May 9 09:34:13 CDT 2016";
    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
    Date d = dateFormat.parse(myDate);
    System.out.println(d);  // this is not formatted printing Mon May 09 16:34:13 CEST 2016
    System.out.println(dateFormat.format(d)); // this is printed using the same format you use above
}

答案 1 :(得分:0)

tl; dr

您的印度时间已正确调整,比芝加哥时间早10.5小时。功能,不是错误。 (我假设您的:56秒是您提问中的错字。)

如果您不想进行此类调整,而是希望将同一日期和同一时间分配给其他时区,请执行以下操作:

ZonedDateTime.parse(
    "Mon May 9 09:34:13 CDT 2016" ,  // If at all possible, avoid using such an awful format for exchanging date-time strings. Always use standard ISO 8601 formats instead.
    DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" )
)                                    // Returns a `ZonedDateTime` object.
.withZoneSameLocal( 
    ZoneId.of( "Asia/Kolkata" ) 
)                                    // Returns a fresh `ZonedDateTime` object, with values based on the original but for the change in assigned zone.
.toString()                          // Generates a String is standard ISO 8601 format, extending the standard by appending the name of the time zone in square brackets.
  

2016-05-09T09:34:13 + 05:30 [亚洲/加尔各答]

我们得到的日期和时间相同,但是与UTC的偏移量不同,这意味着时间不同,时间轴上的时间不同。

更正值

[注意:我假设您的:56中的Mon May 09 20:04:56 IST 2016是一个错字,应该是:13。 ]

字符串Mon May 9 09:34:13 CDT 2016Mon May 09 20:04:13 IST 2016代表同一时刻。这是一个功能,而不是错误。如果用CDT来表示某个时区,例如America/Chicago,则该日期的值表示比世界标准时间-05:00落后五个小时的时刻。如果用IST表示时区,例如Asia/Kolkata,则该日期的印度比世界标准时间+05:30提前五个半小时。将这些偏移量相加,我们将相差十个半小时。这很适合:09:34:13加上10.5小时就是20:04:13

换句话说,如果芝加哥某人正在电话上与加尔各答某人交谈,如果他们俩都在自己墙上的时钟上抬头,一个人会看到09:34:13,而另一个人会看到20 :04:13。

也许您想故意调整时区,但是用相同的时间在不同的时区中重新创建相同的日期。 不是是同一时刻,这将是时间轴上的不同点。参见下面的代码。

java.time

您正在使用麻烦的旧类,而这些旧类早已被现代的 java.time 类所取代。

在可能的情况下,避免操纵字符串作为处理日期时间的一种方式。相反,请使用智能对象,而不要使用哑字符串。

Instant instant = Instant.now() ;  // Capture current moment in UTC.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; 
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, but different wall-clock time.

如果必须将日期时间值作为文本交换,请使用标准ISO 8601格式,而不要使用“问题”中所示的格式。

此外,切勿使用3-4个字母的伪时区,例如CDTIST。这些不是真实的时区,没有标准化,并且许多不是唯一的(!)。使用全时区名称是IANA-specified Continent/Region格式。

但是直接针对您的问题,解析字符串Mon May 9 09:34:13 CDT 2016。定义要匹配的格式模式。

String input = "Mon May 9 09:34:13 CDT 2016";

DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
  

zdt.toString():2016-05-09T09:34:13-05:00 [美国/芝加哥]

ZonedDateTime::withZoneSameInstant

调整为印度时间。

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata );
  

zdtKolkata.toString():2016-05-09T20:04:13 + 05:30 [亚洲/加尔各答]

与旧类相同的行为。在09:34:13上增加10.5小时即可获得20:04:13。时间轴上的相同时刻,相同点,但挂钟时间不同。

ZonedDateTime::withZoneSameLocal

但是,如果您想要相同的日期和相同的时间,却又切换出时区怎么办?这会导致时间轴上的时刻不同,地点不同(假设两个区域的偏移量不同)。 ZonedDateTime确实通过ZonedDateTime::withZoneSameLocal​(ZoneId zone)方法支持此操作。

ZonedDateTime zdtSameLocalKolkata = zdt.withZoneSameLocal( zKolkata );
  

zdtSameLocalKolkata.toString():2016-05-09T09:34:13 + 05:30 [亚洲/加尔各答]

现在,我们看到时间不变,仍然是09:34:13。但是,与UTC的偏移量与芝加哥不同,因此我们知道 not 并不代表同一时刻。

您可以通过将两者都调整为UTC来验证它们是否是不同的时刻。进行调整的简单方法是提取Instant对象。根据定义,Instant始终使用UTC。

Instant instantOfZdtChicago = zdt.toInstant() ;
Instant instantOfZdtSameLocalKolkata = zdtSameLocalKolkata.toInstant():
  

instantOfZdtChicago.toString():2016-05-09T14:34:13Z

     

instantOfZdtSameLocalKolkata.toString():2016-05-09T04:04:13Z


关于 java.time

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

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

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

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?