将带有zoneId的字符串本地日期转换为UTC Offsetdate JAVA

时间:2017-11-16 15:43:34

标签: java date java-8 utc java-time

我试图将巴西本地日期转换为UTC格式。我已经开发出了我的解决方案,但我确信它可以改进。我一直在寻找其他问题,但没有成功。

我的问题是当我使用:

处理Date对象时
Instant endDateTime = questionDate.toInstant();

我收到的UTC日期为"2017-11-16T00:00:00Z",但这应该是巴西本地日期(不正确,因为它有一个尾随"Z"),当我尝试转换为UTC时,我会收到相同的输出。

另一方面,如果我使用ZoneDateTime类并使用LocalDateTime对象构建日期,我将丢失输出中的秒数:"2017-11-16T02:00Z"。当我使用时会发生这种情况:

LocalTime.of(hour, minutes, seconds);

我搜索LocalTime课程,我认为这是因为分钟或秒数0,但我不确定。

解决方案的问题:

  1. 响应时间
  2. 我希望Java 8具有一组功能,使其更简单明了
  3. 前提条件:

    • 我不能使用Joda库
    • 结果必须为OffsetDateTime class
    • 输入:日期"2017-11-16"
    • 输出:"2017-11-16T02:00:00Z"

    这是我的解决方案:

    private static OffsetDateTime processDate(Date questionDate) {
      Instant endDateTime = questionDate.toInstant();
      ZoneId zoneId = ZoneId.of(ZONEID);
      String [] date = endDateTime.toString().split("T");
      LocalDateTime localDateTime = convertLocalTimeToUtc(date);
      ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
      ZonedDateTime utcDate = zonedDateTime.withZoneSameInstant(ZoneOffset.UTC);
      return utcDate.toOffsetDateTime();
    }
    
    private static LocalDateTime convertLocalTimeToUtc(String[] dateFromCountry) {
      LocalDate date = processDate(dateFromCountry[0]);
      LocalTime time = processTime(dateFromCountry[1]);
      return  LocalDateTime.of(date, time);
    }
    
    private static LocalDate processDate(String dateFromCountry) {
      String [] partsOfDate = dateFromCountry.split("-");
      int year = Integer.parseInt(partsOfDate[0]);
      int month = Integer.parseInt(partsOfDate[1]);
      int day = Integer.parseInt(partsOfDate[2]);
      return LocalDate.of(year, month, day);
    }
    
    private static LocalTime processTime(String dateFromCountry) {
      String [] partsOfTime = dateFromCountry.split(":");
      int hour = Integer.parseInt(partsOfTime[0]);
      int minutes = Integer.parseInt(partsOfTime[1]);
      int seconds = Integer.parseInt(partsOfTime[2].substring(0,1));
      return LocalTime.of(hour,minutes,seconds);
    }
    

1 个答案:

答案 0 :(得分:4)

如果您的输入是java.util.Date,则可以摆脱所有字符串操作:

//simulate your input
Instant input = Instant.parse("2017-11-16T00:00:00Z");
Date d = Date.from(input);    

//transformation code starts here
Instant instant = d.toInstant();

ZonedDateTime localInstant = instant.atZone(ZoneOffset.UTC);
ZonedDateTime sameLocalInBrazil = utcInstant.withZoneSameLocal(ZoneId.of("Brazil/East"));
OffsetDateTime sameInstantUtc = sameLocalInBrazil.toOffsetDateTime()
                                      .withOffsetSameInstant(ZoneOffset.UTC);

这将返回一个值为2017-11-16T02:00Z的OffsetDateTime,如你所愿。

请注意,OffsetDateTime没有格式化 - 因此对象确实知道其秒数设置为0,但默认的toString方法不会打印它们。如果要用秒打印,可以使用格式化程序:

//Formatting
System.out.println(sameInstantUtc.format(DateTimeFormatter.ISO_INSTANT));

打印2017-11-16T02:00:00Z

如果您的输入是java.sql.Date,则可以采用略有不同的策略:

LocalDate d = sqlDate.toLocalDate();
ZonedDateTime localInstant = d.atStartOfDay(ZoneOffset.UTC);

其余的代码将是相同的。