【问题标题】:How to Convert a 2021-09-29T17:04:31.0000 +05:30 to 2021-09-29 17:04:31.0000000 Asia/Calcutta In Java?如何在 Java 中将 2021-09-29T17:04:31.0000 +05:30 转换为 2021-09-29 17:04:31.0000000 Asia/Calcutta?
【发布时间】:2021-11-25 19:41:01
【问题描述】:

如何在 Java 中将 2021-09-29T17:04:31.0000 +05:30 转换为 2021-09-29 17:04:31.0000000 Asia/Calcutta

这里还有其他问题- 我尝试了很多方法从offset(+05:30) 获取timezone(Asia/Calcutta),但无法获取。 有人可以帮忙吗?

【问题讨论】:

  • 您无法从偏移量中获取区域,因为偏移量只是与 UTC 的偏移量,但它不会告诉您实际应用的位置。区域会告诉您它在哪里以及它使用的偏移量,它甚至会考虑夏令时。这意味着您不能从偏移量中导出区域,但反过来也是可能的。
  • 什么情况?例如,如果您总是必须使用相同的时区或偏移量,您能否更详细地解释一下?问题中的更多信息可能会导致 cmets 和答案中的更多信息。请分享一些...
  • 你不能。 +05:30 也可能意味着亚洲/科伦坡。对于其他偏移量,列表通常会变得更长。例如,我当前的偏移量 +02:00 可能意味着 Europe/Sarajevo、Africa/Khartoum、Africa/Cairo、Africa/Mbabane、Europe/Amsterdam、Europe/Tirane、Africa/Blantyre、Europe/Busingen、Europe/Zagreb、Europe /布鲁塞尔,非洲/布琼布拉,欧洲/罗马,南极洲/巨魔,欧洲/波德戈里察,欧洲/安道尔,欧洲/布达佩斯,欧洲/斯科普里,非洲/约翰内斯堡,欧洲/梵蒂冈,欧洲/奥斯陆,非洲/温得和克,欧洲/卢布尔雅那、Arctic/Longyearbyen、Atlantic/Jan_Mayen、Europ...(太长了 403 个字符)
  • 你是对的@OleV.V。在这种情况下我怎么知道确切的时区
  • 很抱歉重复一遍:你不能。 @PravinMangalam 不是来自你收到的那个字符串。您可以向消息来源的人询问他们打算使用哪个时区,当然,也许他们知道。

标签: java datetime timestamp timestamp-with-timezone datetimeformatter


【解决方案1】:

由于您无法(可靠地)从偏移中派生区域,因此您可能需要使用解决方法/不同的方法。

以下示例使用合适的DateTimeFormatter 将输入String 解析为OffsetDateTime,然后创建所需的ZoneId,并将其应用于OffsetDateTime 以创建ZonedDateTime

public static void main(String[] args) {
    // your example input
    String offsetTime = "2021-09-29T17:04:31.0000 +05:30";
    // define a formatter that parses a String of this format
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSS xxx");
    // then parse it to an object that knows date, time and offset
    OffsetDateTime odt = OffsetDateTime.parse(offsetTime, dtf);
    // print the result
    System.out.println(odt);

    // now define the desired zone
    ZoneId asiaCalcutta = ZoneId.of("Asia/Calcutta");
    // and use the offset-aware object to apply the zone
    ZonedDateTime zdt = odt.atZoneSameInstant(asiaCalcutta);
    // print it
    System.out.println(zdt);
}

这个输出

2021-09-29T17:04:31+05:30
2021-09-29T17:04:31+05:30[Asia/Calcutta]

请注意:只有当偏移量和区域实际匹配时,这才会保持相同的偏移量。我不知道你的具体要求,所以只有你才能知道这种方法是否适合你的情况。

如果您想找出当前使用特定偏移量的时区,然后让您的代码决定哪个是正确的,您可能需要查看this question and its answers

【讨论】:

  • 我想从 +05:30 起飞 [Asia/Calcutta]。这个 +05:30 可以是它动态到来的任何有效偏移量。这就是为什么我不能这样做 ZoneId asiaCalcutta = ZoneId.of("Asia/Calcutta"); // 并使用偏移感知对象应用区域 ZonedDateTime zdt = odt.atZoneSameInstant(asiaCalcutta); // 打印它 System.out.println(zdt);
  • @PravinMangalam 然后点击我答案末尾的链接
  • 谢谢 解决问题 final TimeZone timeZone = TimeZone.getTimeZone(time.getZone()); // String str = Arrays.stream(TimeZone.getAvailableIDs(timeZone.getRawOffset())).peek(System.out::println).findFirst().get();这会将时区作为字符串返回给我,我需要将其作为参数放在下面。 ZoneId asiaCalcutta = ZoneId.of("Asia/Calcutta");
  • @PravinMangalam 对于来自欧洲/巴黎时区的字符串(9 月偏移 +02:00),您的解决方案给了我非洲/阿尔及尔。另外我建议你不要使用TimeZone。该课程设计不良且早已过时。坚持现代的ZoneIdZoneRules。它们为您提供所需的所有功能。
【解决方案2】:

我尝试编写此代码以涵盖三种可能性 String parameterLocalDateTime parameterZonedDateTime Parameter

      import java.time.LocalDateTime;
      import java.time.ZoneId;
      import java.time.ZonedDateTime;
      import java.time.format.DateTimeFormatter;

      public class SpecialFormater {

   // parameter : ZonedDateTime
   public static String specialFormaterZonedDateTime(ZonedDateTime zdt) {

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
    ZoneId zid = zdt.getZone();
    System.out.println("Your initial format                =" + zdt);
    String result = "Your expected format               =" + zdt.format(formatter) + " " + zid;

    return result;
}
  // parameter : LocalDateTime
 public static String specialFormaterLocalDateTime(LocalDateTime dt) {

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");

    ZoneId zid = ZoneId.of("Asia/Calcutta");

    System.out.println("Your initial format                =" + dt);
    ZonedDateTime zdt = ZonedDateTime.of(dt, zid);
    System.out.println("Your zoned dateTime default format =" + zdt);
    String result = "Your expected format               =" + dt.format(formatter) + " " + zid;

    return result;
}

// Parameter : String
public static String specialFormaterString(String localDateTime) {
    System.out.println("String before formatting   =" + localDateTime);
    String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSS xxx";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    LocalDateTime dt = LocalDateTime.parse(localDateTime, formatter);
    ZoneId zid = ZoneId.of("Asia/Calcutta");

    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
    String result = "String after  formatting   =" + dt.format(formatter2) + " " + zid;
    return result;
}

public static void main(String[] args) {
System.out.println("specialFormaterLocalDateTime");
    System.out.println(specialFormaterLocalDateTime(LocalDateTime.now()));
    System.out.println("***********");
    System.out.println();
    System.out.println("specialFormaterString");
    System.out.println(specialFormaterString("2021-09-29T17:04:31.0000 +05:30"));
    System.out.println("**********");       
    System.out.println();
    System.out.println("specialFormaterZonedDateTime");
    System.out.println(specialFormaterZonedDateTime(ZonedDateTime.now()));
}
}

输出:

  specialFormaterLocalDateTime
  Your initial format                =2021-10-06T12:35:45.029
  Your zoned dateTime default format =2021-10-06T12:35:45.029+05:30[Asia/Calcutta]
  Your expected format               =2021-10-06 12:35:45.0290000 Asia/Calcutta
  ***********

  specialFormaterString
  String before formatting   =2021-09-29T17:04:31.0000 +05:30
  String after  formatting   =2021-09-29 17:04:31.0000000 Asia/Calcutta
  **********

  specialFormaterZonedDateTime
  Your initial format                =2021-10-06T12:35:45.064+02:00[Europe/Paris]
  Your expected format               =2021-10-06 12:35:45.0640000 Europe/Paris

【讨论】:

    【解决方案3】:

    如何使用 java.time 获取与偏移量匹配的 some 时区

    我倾向于从您在 Arvind Kumar Avinash 回答下的评论中了解到,您只需采用具有正确偏移量(或您认为是正确偏移量)的第一个时区即可解决该问题。当然,现代 Java 日期和时间 API java.time 可以做到这一点。我想告诉你一个方法。

        String input = "2021-09-29T17:04:31.0000 +05:30";
        
        // Remove space and parse
        OffsetDateTime dateTime = OffsetDateTime.parse(input.replace(" ", ""));
        ZoneOffset offset = dateTime.getOffset();
        
        // Find and convert to a zone that matches the offset (there will usually be many)
        ZonedDateTime zonedDateTime = ZoneId.getAvailableZoneIds()
                .stream()
                .map(ZoneId::of)
                .map(dateTime::atZoneSameInstant)
                .filter(zdt -> zdt.getOffset().equals(offset))
                .findFirst()
                // If all else fails, use the offset as time zone
                .orElse(dateTime.atZoneSameInstant(offset));
        
        // Convert to 2021-09-29 17:04:31.0000000 Asia/Calcutta format
        String result = zonedDateTime.format(FORMATTER);
        
        System.out.println(result);
    

    我已使用此格式化程序来格式化输出:

    private static final DateTimeFormatter FORMATTER
            = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSS VV", Locale.ROOT);
    

    输出是(在我的 Java 11 上):

    2021-09-29 17:04:31.000000 亚洲/加尔各答

    Asia/Kolkata 是时区的现在名称,以前称为 Asia/Calcutta。够近了吗?

    在我的代码中,我考虑了不存在合适时区的情况。让我们用我认为不会在任何实时区域中使用的偏移量来看看这个:

        String input = "2021-10-06T18:54:31.0000 +00:30";
    

    2021-10-06 18:54:31.000000 +00:30

    如果您不希望这样,您至少需要将调用行更改为orElse()

    【讨论】:

    • 在我的情况下,这也不合适,因为我需要来自偏移量的时区,而偏移量不是唯一的。实际日期在 oracle - 28-OCT-2021 02:36:08 AM Europe/Paris 我在 MSSQL DatetimeOffset 中将其保存为 2021-10-28T02:36:08.000 +02:00 现在我想在屏幕上显示为 2021-10-28T02:36:08.000 +02:00 Europe/Paris 但是当我使用您的代码进行转换时,我得到这个 2021-10-28 02:36:08.000000 Africa/Cairo Where timezone is not match to我的。
    • 没错。这也是我之前的 cmets 的意思。
    • 很抱歉,您刚刚发现架构中的一个缺陷:MySQL 没有存储所有需要的数据。现在您必须确定是否可以以任何合适的 MySQL 日期时间格式存储区域,如果存在,则重新设计存储机制以也存储区域。我认为this answer to a related question 在这里可能会有所帮助……
    猜你喜欢
    • 2020-01-26
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 2021-11-01
    相关资源
    最近更新 更多