我想使用 java 中具有不同时区的字符串生成日期

I wanted to generate the date using a string with various time zones in java

我的输入:2021-01-07T18:54:00.000 - UTC(TZ)
我的预期输出:
格林威治标准时间 +5:30 - 2021-01-08T00:24:00.000
格林威治标准时间 -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);
    String sDate1="2021-01-05T00:00:00";
    SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    //UTC
    isoFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    Date date = isoFormat.parse(sDate1);
    System.out.println(isoFormat.format(date));
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);     
    //Here you set to your timezone
    isoFormat.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
    System.out.println(isoFormat.format(calendar.getTime()));
    //Here you set to your timezone
    isoFormat.setTimeZone(TimeZone.getTimeZone("GMT-12:00"));
    System.out.println(isoFormat.format(calendar.getTime()));

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

  1. 不要将日期和时间作为字符串保存或处理。将它们保存为 Instant 个对象。当您获取字符串输入时,将其解析为 Instant。只有当你需要给字符串输出的时候,把你的Instant转换成合适时区的ZonedDateTime,格式化成需要的字符串。
  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 偏移量。以 region/city 格式指定时区,例如 Asia/KolkataAsia/Colombo.
  4. 使用 java.time,现代 Java 日期和时间 API,用于所有日期和时间工作。它比您在问题中使用的旧 类 和您自己的答案 SimpleDateFormatCalendarTimeZone 要好得多。它们的设计很差,而且早就过时了。您已经在 java.timeDateTimeFormatterLocalDate 的路上了。全力以赴。

我猜这不是用户输入,因为虽然 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 就像那样。 Instant 是独立于时区的时间点。

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

    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

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

链接