无法将 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
java.util.Date

没有任何时区信息。它只包含一个值:自 unix 纪元(1970-01-01T00:00Z年,或 1907 年 1 月 1 日,UTC午夜)以来的毫秒数。

这个毫秒数在世界各地都是一样的。不同的是每个时区中的相应日期和时间。示例:现在,此米利斯值为1505481835424,在 UTC 中对应于2017-09-15T13:23:55.424Z。此值对应于圣保罗的 10:23 AM、加尔各答的 18:53、伦敦的 14:23 等。每个时区的本地日期/时间都不同,但每个人的 millis 值都相同。

这就是为什么你不转换Date本身:米利斯值是相同的,没有必要改变它。您可以更改的是此日期在不同时区中的表示形式。

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)有很多问题和设计问题,它们正在被新的API所取代。

在Android中,你可以使用ThreeTen Backport,这是Java 8新的日期/时间类的一个很好的反向移植。要使其正常工作,您还需要ThreeTenABP(有关如何使用它的更多信息) 这里).

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

// 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

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

相关内容

  • 没有找到相关文章

最新更新