日期时区变换

问题描述:

我已经完成了从UTC字符串到本地时区日期的转换方法,但它只是返回与字符串中相同的日期。这里有什么问题?日期时区变换

public static Date getUTCToDate(String utc){ 
    // String exampleOfUTCTime = "2016-09-27T19:35:32.717"; 

    try{ 
     Log.d("asd-timeBefore", "getUTCToDate: " + utc); 
     DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 
     formatter.setTimeZone(TimeZone.getDefault()); 
     Date d = formatter.parse(utc); 
     Log.d("asd-timeAfter", "getUTCToDate: " + d); 
     return d; 
    } catch (ParseException e){ 
     e.printStackTrace(); 
    } 
    return null; 
} 
+1

您正在为格式化程序设置不正确的时区 – xAqweRx

+0

您想要的时区的偏移量是多少? –

+0

我需要使用本地时区,因为应用程序将用于各个国家 –

试着改变你的代码,就像这样。这将UTC时间转换为本地时区:

public static Date getUTCToDate(String utc){ 
    // String exampleOfUTCTime = "2016-09-27T19:35:32.717"; 

    try{ 
     Log.d("asd-timeBefore", "getUTCToDate: " + utc); 
     DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 
     formatter.setTimeZone(TimeZone.getTimeZone("UTC")); 
     Date d = formatter.parse(utc); 
     Log.d("asd-timeAfter", "getUTCToDate: " + d); 
     return d; 
    } catch (ParseException e){ 
     e.printStackTrace(); 
    } 
    return null; 
} 
+0

它的工作原理!但是如何?我正在接收像'exampleOfUTCTime'这样的字符串,所以我想我需要将它转换为本地时区,但似乎Android/Java本身关心本地时区。 –

+0

我不确定这是否正确。 –

+0

该转换是由系统自动完成的。如果你正在设置UTC时区 - > SimpleDateFormat的想法像“好的,这是UTC”,但是当你给这个Date - >它会自动转换为本地时区。思想日期没有时区 - >内部函数有'SimpleDateFormatter'它使用默认时区(当地时区) – xAqweRx

如果你想在UTC格式格式化的日期和时间,那么你应该做这样的

formatter.setTimeZone(TimeZone.getTimeZone("UTC")); 

答案与setTimeZone是正确的,但作为替代方案,您可以尝试在字符串中指定UTC本身并注明您正在使用时区SimpleDateFormat类,如:

public static Date getUTCToDate(String utc){ 
    // String exampleOfUTCTime = "2016-09-27T19:35:32.717 UTC"; 

    try{ 
     System.out.println("getUTCToDate: " + utc); 
     DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS z"); 
     Date d = formatter.parse(utc); 
     System.out.println("getUTCToDate: " + d); 
     return d; 
    } catch (ParseException e){ 
     e.printStackTrace(); 
    } 
    return null; 
} 

我需要使用本地时区,因为应用程序将用于各个国家。

如果要格式化上使用客户端的时区服务器端的日期,那么你将不得不通过在从客户端分钟GMT时间偏移。使用此JavaScript代码:

var offset = new Date().getTimezoneOffset(); 

然后通过这个偏移你的方法作为参数:

public static Date getUTCToDate(String utc, int offsetInMinutes) { 
    // String exampleOfUTCTime = "2016-09-27T19:35:32.717"; 

    try { 
     Log.d("asd-timeBefore", "getUTCToDate: " + utc); 
     DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z"); 
     long offset = -1L*60*1000*offsetInMinutes; 
     String[] timezones = TimeZone.getAvailableIDs(offset); 
     formatter.setTimeZone(timezones[0]); 
     Date d = formatter.parse(utc); 
     Log.d("asd-timeAfter", "getUTCToDate: " + d); 
     return d; 
    } catch (ParseException e){ 
     e.printStackTrace(); 
    } 
    return null; 
} 

评论:

你会发现,我包括Z的日期格式参数在您的SimpleDateFormat。这将包括显示为距GMT时间的小时偏移的时区。

Java Date只是一个时间点,不考虑偏移量。如果你想要客户端的时区信息,你必须自己带上它。

TL;博士

LocalDateTime.parse("2016-09-27T19:35:32.717").atZone(ZoneOffset.UTC) 

详细

你输入的字符串一个UTC值:2016-09-27T19:35:32.717。该字符串缺少关于offset-from-UTCtime zone的任何信息。

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

LocalDateTime

解析字符串作为LocalDateTime对象缺乏任何偏移或时区。

该输入字符串恰好符合日期 - 时间字符串的ISO 8601标准。解析/生成字符串时,java.time类默认使用ISO 8601格式。所以不需要指定格式化模式。

LocalDateTime ldt = LocalDateTime.parse("2016-09-27T19:35:32.717"); 

OffsetDateTime

如果上下文,你肯定知道字符串是为了代表UTC了一会儿,然后应用偏移获得OffsetDateTime。使用预定义常数ZoneOffset.UTC

OffsetDateTime odt = ldt.atZone(ZoneOffset.UTC); 

从那里,你可以使用DateTimeFormatter生成字符串各种格式,如果需要的话。

ZonedDateTime

如果你想通过一些特定地区的时区的镜头,查看同一时刻,应用ZoneId获得ZonedDateTime

时区与UTC的偏移量为用于处理异常情况(如夏令时(DST))的一组规则。

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

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = odt.atZoneSameInstant(z); 

如果需要,您可以获取用户当前的默认时区。但请注意,此默认设置可以随时更改,即使在运行时期间也可以更改。因此,如果重要的话,您应该向用户询问预期的/所需的时区,而不是假设。

ZoneId z = ZoneId.systemDefault(); 

关于java.time

java.time框架是建立在Java 8和更高版本。这些类代替了日期 - 时间类legacy,如java.util.Date.Calendar,& java.text.SimpleDateFormat

Joda-Time项目现在位于maintenance mode,建议迁移到java.time。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。规格是JSR 310

从何处获取java.time类?

ThreeTen-Extra项目与其他类扩展java.time。这个项目是未来可能增加java.time的一个试验场。您可以在这里找到一些有用的类,如Interval,YearWeek,YearQuartermore

+0

这是绰绰有余和预期。要检查这些 - 看起来有趣! –