【问题标题】:Convert string local date with zoneId to UTC Offsetdate JAVA将带有 zoneId 的字符串本地日期转换为 UTC Offsetdate JAVA
【发布时间】:2017-11-16 15:43:33
【问题描述】:

我正在尝试将巴西本地日期转换为 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 有一组函数可以让这更简单明了

前提条件:

  • 我无法使用 Joda 库
  • 结果必须是 OffsetDateTime 类
  • 输入:日期"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);
}

【问题讨论】:

  • 试试OffsetDateTime类的静态方法——ofInstant(Instant instant, ZoneId zone)返回OffsetDateTime...
  • @Grasshopper 我试过但它返回 "2017-11-16T22:00-02:00" 。就像将原始日期作为UTC日期一样。我正在寻找相反的行为
  • 您的意见是什么? java.util.Date 还是 java.sql.Date?你能显示准确的输入吗(例如:long millis = xxx; Date d = new Date(millis))?
  • 你从哪里得到日期?如果来自数据库,则可以通过使用不同的列类型来解决问题。

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


【解决方案1】:

如果你的输入是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);

这将返回一个 OffsetDateTime,其值为 2017-11-16T02:00Z,正如您所期望的那样。

请注意,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);

其余的代码都是一样的。

【讨论】:

    猜你喜欢
    • 2012-07-02
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2020-02-03
    • 2020-03-21
    • 1970-01-01
    • 2018-02-23
    相关资源
    最近更新 更多