2017-09-15 112 views
1

我想将UTC日期转换为IST。但令我惊讶的是,在转换所有内容之后,它仍然只以UTC返回。这怎么可能?无法将UTC转换为IST,它仍然只返回UTC

输入:

StartDateTimeUtc='2017-09-15T14:00:00', 
EndDateTimeUtc='2017-09-15T15:00:00' 

代码:再次

public static final String DATE_FORMATE_CURRENT = "yyyy-MM-dd'T'HH:mm:ss"; 

Date meetingStartDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.StartDateTimeUtc); 
Date meetingEndDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.EndDateTimeUtc); 

      //Convert Date to String 
      DateFormat df = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT); 
      String meetinStartDateString = df.format(meetingStartDate); 
      String meetingEndDateString = df.format(meetingEndDate); 

      //Convert String Date to IST 
      SimpleDateFormat dftwo = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT); 
      dftwo.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata")); 
      Date date = null; 
      Date datetwo = null; 
      try { 
       date = dftwo.parse(meetinStartDateString); 
       datetwo = dftwo.parse(meetingEndDateString); 
      } catch (ParseException e) { 
       e.printStackTrace(); 
      } 

      dftwo.setTimeZone(TimeZone.getDefault()); 
      String formattedStartDate = dftwo.format(date); 
      String formattedEndDate = dftwo.format(datetwo); 

      //Convert String Date back to Date format so that we can pass into Calendar code 
      Date meetingStartDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedStartDate); 
      Date meetingEndDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedEndDate); 

输出UTC:

Start Date : Fri Sep 15 14:00:00 GMT+05:30 2017 
End Date : Fri Sep 15 15:00:00 GMT+05:30 2017 
+0

'GMT + 05:30'不是UTC。另外,如果你可以请** **问题并添加'model.StartDateTimeUtc'和'model.EndDateTimeUtc'的值,以及正确的输出结果是什么。无论如何,如果您直接打印日期对象,请记住日期[没有时区信息](https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util -date),你看到的是'toString()'方法(它在后台使用JVM默认时区)的结果。 – 2017-09-15 13:14:42

+1

Thanks @ Hugo:我已经编辑并添加了开始和结束时间。谢谢 – Golmaal

+0

麻烦的Date类现在被java.time类取代,特别是'Instant'。例如:'Instant.now()。atZone(“Asia/Kolkata”)' –

回答

0

一个java.util.Datedoesn't have any timezone information。它只包含一个值:自unix时代以来的毫秒数(1970-01-01T00:00Z或1月1日st 1907,在午夜UTC)。

这个毫秒数是相同的,在世界各地。每个时区的相应日期和时间有什么不同?例如:现在,这个毫秒值是1505481835424,这对应于UTC,到2017-09-15T13:23:55.424Z。这一价值相当于圣保罗上午10:23,加尔各答18:53,伦敦14:23等。每个时区的本地日期/时间都不相同,但每个人的毫秒值都是一样的。

这就是为什么你不转换Date本身:millis的价值是相同的,没有必要改变它。你可以改变的是这个日期的表示在不同的时区。

SimpleDateFormat默认情况下使用JVM默认时区来分析日期。但是,如果您知道输入位于特定区域中,则必须在格式化程序中设置。因此,要分析你的投入,你必须做到:

String startDateTimeUtc = "2017-09-15T14:00:00"; 
String endDateTimeUtc = "2017-09-15T15:00:00"; 

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 
// input is in UTC 
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 

// parse dates 
Date meetingStartDate = sdf.parse(startDateTimeUtc); 
Date meetingEndDate = sdf.parse(endDateTimeUtc); 

的2个Date上述目的将对应于14:00和15:00 UTC(这是在加尔各答时区同19:30和20:30 )。

但如果你只是直接打印的Date对象(使用System.out.println,伐木,甚至检查他们在调试器的值),它会含蓄调用toString()方法,它使用的幕后JVM默认的时区,导致你看到的输出(Fri Sep 15 14:00:00 GMT+05:30 2017)。

如果你想在一个特定的格式打印,并在特定的时区,你需要另一个格式化:

// another formatter for output 
SimpleDateFormat outputFormat= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 
// output will be in Asia/Kolkata timezone 
outputFormat.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata")); 

System.out.println(outputFormat.format(meetingStartDate)); 
System.out.println(outputFormat.format(meetingEndDate)); 

输出将是:

2017-09-15T19 :30:00
2017-09-15T20:30:00

对应于加尔各答时区相同的UTC日期。

只要记住:你不要在时区之间转换Date(因为它们的毫毫值是“绝对”的 - 它们对世界上每个人都是一样的)。您只需更改这些日期的String表示(特定时区中的相应日期/时间)。


新的Java日期/时间API

老班(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,他们正在被新的API取代。

在Android中,您可以使用ThreeTen Backport,它是Java 8新日期/时间类的一个很好的后端。要使其工作,您还需要ThreeTenABP(更多关于如何使用它here)。

这个新的API在每种情况下都有许多不同的日期/时间类型。在这种情况下,输入具有日期和时间,但没有时区信息,所以首先我把它解析为org.threeten.bp.LocalDateTime,使用org.threeten.bp.format.DateTimeFormatter

// parse the inputs 
DateTimeFormatter fmt = DateTimeFormatter.ISO_LOCAL_DATE_TIME; 
LocalDateTime startDt = LocalDateTime.parse(startDateTimeUtc, fmt); 
LocalDateTime endDt = LocalDateTime.parse(endDateTimeUtc, fmt); 

然后我用一个org.threeten.bp.ZoneOffset将它们转换为UTC,后来org.threeten.bp.ZoneId将其转换为另一个时区。其结果将是一个org.threeten.bp.ZonedDateTime

// input is in UTC 
ZoneOffset utc = ZoneOffset.UTC; 
// convert to Asia/Kolkata 
ZoneId zone = ZoneId.of("Asia/Kolkata"); 
ZonedDateTime start = startDt.atOffset(utc).atZoneSameInstant(zone); 
ZonedDateTime end = endDt.atOffset(utc).atZoneSameInstant(zone); 

然后,我使用相同DateTimeFormatter格式化输出:

System.out.println(fmt.format(start)); 
System.out.println(fmt.format(end)); 

的输出是:

2017-09-15T19:30: 00
2017-09-15T20:30:00

请注意,我不需要在格式化程序中设置时区,因为时区信息位于对象中(它们负责执行转换)。