我正在尝试将UTC日期转换为IST。但令我惊讶的是,在转换完所有内容后,它仍然只返回UTC。怎么可能?
INPUT:
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 :(得分:0)
java.util.Date
doesn't have any timezone information。它只包含一个值:自unix世纪(1970-01-01T00:00Z
或1月1日 st 1907年, UTC 午夜)以来的毫秒数。
这个毫秒数在世界各地都是一样的。不同的是每个时区的相应日期和时间。示例:此时,此millis值为1505481835424
,与UTC对应2017-09-15T13:23:55.424Z
。同样的值对应于圣保罗的10:23 AM,加尔各答的18:53,伦敦的14:23等等。每个时区的本地日期/时间不同,但每个人的millis值都相同。
这就是为什么你不转换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
个对象将对应于UTC时间14:00和15:00(与加尔各答时区的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
表示(特定时区中的相应日期/时间)。
旧类(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design issues,它们将被新API取代。< / p>
在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
请注意,我不需要在格式化程序中设置时区,因为时区信息位于对象中(它们负责进行转换)。