【问题标题】:Convert datetime to a different time zone将日期时间转换为不同的时区
【发布时间】:2014-12-29 14:53:57
【问题描述】:

我将时间和时间的时区与外部组件分开。 时间格式为“MMM dd yyyy hh:mma”。例如:2014 年 10 月 31 日 12:54PM,此时的时区单独接收。

在保存到数据库之前,我需要将此时间标准化为 EST 时区。我试过日历(我不认为这可以用 java Date 完成),但是输出有相当大的不一致,然后经过一些谷歌搜索,认为 Joda 有更好的支持并切换到它。但我得到了以下异常。

    String clientTimeZone = "America/New_York";
    String value = "Nov 25 2014  2:18PM";
     DateTimeFormatter df = DateTimeFormat.forPattern("MMM dd yyyy hh:mma");//.withLocale(Locale.ENGLISH);
            DateTime temp = df.withZone(DateTimeZone.forID(clientTimeZone)).withOffsetParsed().parseDateTime(value);
            DateTime date = temp.withZone(DateTimeZone.forID("America/New_York"));
            Timestamp ts = new Timestamp(date.getMillis());
            Date d = new Date(ts.getTime());
            System.out.println(d.toString());

我明白了:

java.lang.IllegalArgumentException:格式无效:“2014 年 11 月 25 日下午 2:18”在“下午 2:18”时格式错误 在 org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:899) 在 LearnJoda.main(LearnJoda.java:34)

知道可能是什么问题吗?

【问题讨论】:

  • 可能重复:link
  • 我为此创建了一个测试用例,它似乎有效。查看hastebin.com/okeqotojip.avrasm - 没有例外。或者,代码中是否缺少某些内容?
  • @wassgren 我刚刚更新了我正在使用的代码示例。我想我明白了。外部系统以小时为单位发送“2”而不是“2”。所以它正在创造一个额外的空间,这似乎是导致问题的原因。如果我删除额外的空间,异常就消失了。有什么办法可以自动处理。我希望我可以要求外部系统来处理这个问题,但我认为我无法完成。
  • 如果你知道你总是有两个空格,你可以把它添加到你的模式中。
  • @SotiriosDelimanolis 它并不总是有 2 个空格。只有时间小于 10 时才有 2 个空格,大于 9 时才有 1 个空格。所以我在模式中添加了 2 个空格,如果时间大于 9 小时,那么它就失败了。因此,在将值发送到格式化程序之前,我用 1 个空格替换了 2 个空格,现在可以使用。

标签: java jodatime


【解决方案1】:

编辑:在 OP 提供更多信息后,答案略有改变。

您可以使用以下模式(您定义的)。

"MMM dd yyyy hh:mma"

但是,由于您的输入字符串取决于它是 2 位数小时还是一位数小时,我建议您使用 String.replace 方法预处理这些值(如 answer 中所建议的那样)。

@Test
public void test() throws JsonProcessingException {
    final String value1 = "Nov 24 2014  2:40PM"; // Double space
    final String value2 = "Nov 24 2014 11:40PM"; // Single space

    // Set up a test time zone
    final ZoneId clientTimeZone = ZoneId.systemDefault();

    // Create the formatter (as previously)
    DateTimeFormatter df = DateTimeFormat.forPattern("MMM dd yyyy hh:mma");


    DateTime temp1 = 
        df.withZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone(clientTimeZone)))
               .withOffsetParsed()
               .parseDateTime(value1.replace("  ", " ")); // replace double space with single space

    DateTime temp2 = 
        df.withZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone(clientTimeZone)))
                .withOffsetParsed()
                .parseDateTime(value2.replace("  ", " ")); // always replace to be sre

    DateTime date1 = temp1.toDateTime(DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/New_York")));
    DateTime date2 = temp2.toDateTime(DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/New_York")));
    Timestamp ts1 = new Timestamp(date1.getMillis());
    Timestamp ts2 = new Timestamp(date2.getMillis());
}

如果您使用的是 Java 8,也可以跳过 Joda,而使用 java.time 包中的 new Java 8 时间和日期函数。例如

DateTimeFormatter df = DateTimeFormatter.ofPattern("MMM dd yyyy h:ma");

【讨论】:

  • 我尝试了这种格式,但我得到了同样的异常。java.lang.IllegalArgumentException: Invalid format: "Nov 24 2014 2:40PM" is malformed at "2:40PM"
  • @SotiriosDelimanolis 很难说。 “hh”表示小时应该是零填充的,但 2 不是零填充的......顺便说一下,出于同样的原因,一天不应该也是“d”而不是“dd”吗?
  • @SotiriosDelimanolis 实际上,没关系。 “解析时,接受任意数量的数字。”对于数字,月份中的哪一天;半天一小时;和分钟都考虑在内。
猜你喜欢
  • 2015-11-27
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 2019-09-07
  • 2016-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多