无法将UTC转换为IST,它仍然只返回UTC

时间:2017-09-15 13:09:29

标签: java android datetime timezone datetime-parsing

我正在尝试将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

1 个答案:

答案 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表示(特定时区中的相应日期/时间)。

Java新日期/时间API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign 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

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