首页 > 解决方案 > 我想在java中使用具有不同时区的字符串生成日期

问题描述

我的输入:2021-01-07T18:54:00.000 - UTC(TZ)
我的预期输出:
GMT +5:30 - 2021-01-08T00:24:00.000
GMT -12:00 - 2021-01-07T06:54: 00.000

Calendar calendar = Calendar.getInstance();
// This line is creating the calendar instance for the current day, I need to create calendar instance for the string which i receive from API
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        
//Here you set to your timezone
sdf.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
String temp1 = sdf.format(calendar.getTime());
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("dd-MM-yyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(temp1, inputFormatter);
String formattedDate = outputFormatter.format(date);
System.out.println(formattedDate);

标签: javadatedatetimecalendartimezone

解决方案


我会退后一步,并建议其他可能更好的方法来做你的事情。我不了解您的大局,因此可能并非我的所有一般性建议都适用于您的情况和要求。但我认为他们很可能会这样做。

  1. 不要将日期和时间保留或处理为字符串。将它们作为Instant对象保存。当您接受字符串输入时,将其解析为Instant. 仅当您需要提供字符串输出时,将您Instant的转换ZonedDateTime为适当时区的 a 并将其格式化为所需的字符串。
  2. 您的字符串采用 ISO 8601 格式,有利于数据交换。ISO 8601 还允许在字符串中使用 GMT 偏移量(UTC 偏移量)。我建议您和您与之通信的系统利用这种可能性来减少误解的风险。UTC 表示为Z,例如2021-01-07T18:54:00.000Z。其他偏移量通常以+HH:MM格式给出,例如2021-01-08T00:24:00.000+05:302021-01-07T06:54:00.000-12:00
  3. 区分时区和与 UTC 或 GMT 的偏移量。在 Java 术语中,时区是地球上的一个地方,具有该地方的人们使用的历史、现在和已知的未来偏移量。由于偏移量在历史期间会发生变化,并且会在我们知道之前发生变化,因此对于时区中的人,使用他们的时区 ID 进行转换,而不是您认为上次检查时正确的 GMT 偏移量。以区域/城市格式指定时区,例如,Asia/KolkataAsia/Colombo
  4. 使用现代 Java 日期和时间 API java.time来处理所有日期和时间工作。SimpleDateFormat与您在问题中使用的旧类和您自己的答案、Calendar和相比,使用它要好得多TimeZone。它们设计得很糟糕,而且早已过时。你已经在使用java.timeDateTimeFormatter路上了。就全力以赴。LocalDate

我猜这不是用户输入,因为虽然 ISO 8601 是人类可读的,但对于用户输入,您可能会得到一个更加用户友好的本地化格式。因此,我假设您从其他系统获得了 UTC 格式的 ISO 8601 字符串。转换成Instant这样:

    String sDate1="2021-01-05T00:00:00Z"; // The trailing Z means UTC
    Instant inst = Instant.parse(sDate1);
    System.out.println(inst);

到目前为止的输出是:

2021-01-05T00:00:00Z

请注意,我们不需要指定任何格式化程序。Instant以 UTC 格式解析 ISO 8601 格式,尾随Z就是这样。AnInstant是独立于时区的时间点。

同样,我假设您需要在某个时区将字符串输出提供给另一个系统(可能是某个前端)。

    ZoneId zone = ZoneId.of("Asia/Colombo");
    String output = inst.atZone(zone)
            .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    System.out.println(output);

2021-01-05T05:30:00+05:30

同样,我们不需要自己构建任何格式化程序。我只用了一个内置的。

链接


推荐阅读