【问题标题】:Custom String from ISO Compliant Date来自 ISO 兼容日期的自定义字符串
【发布时间】:2014-04-10 08:28:43
【问题描述】:

我得到一个日期字符串为 2014-01-11-T00:00:00Z 我想将此日期转换为 20140111 即 YYYYMMDD 它应该是一个字符串。

上面有什么标准的方法/功能可以实现吗?

【问题讨论】:

  • 糟糕,对不起,我忘了提到它的 Java。
  • 没关系 - 你用java标记了它
  • “转换为”是什么意思?如果你只是想从一个字符串中提取年、月、日并放在另一个字符串中,3个子字符串和3个字符串连接就足够了,你不需要创建几个Date对象的负担。
  • “T”前面的连字符是不是错字-T

标签: java date date-format simpledateformat


【解决方案1】:

java.time

您的日期时间字符串2014-01-11-T00:00:00Z 有点奇怪,因为我从未见过T 之前有连字符(-)的日期时间字符串。对于这种字符串,以下模式满足解析要求:

yyyy-M-d-'T'H:m:sXXX

另外,对于java.time API,我建议您将y 替换为u,如this answer 中所述。对于输出字符串,您不需要定义任何模式,因为该模式已经存在一个内置的DateTimeFormatterDateTimeFormatter.BASIC_ISO_DATE

演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d-'T'H:m:sXXX", Locale.ENGLISH);
        OffsetDateTime odt = OffsetDateTime.parse("2014-01-11-T00:00:00Z", dtfInput);
        System.out.println(odt);

        String output = odt.toLocalDate().format(DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(output);
    }
}

输出:

2014-01-11T00:00Z
20140111

注意:

  1. 如果您的日期时间字符串符合ISO 8601,您就不需要明确使用DateTimeFormatter 对象进行解析,即您可以简单地将其解析为
    OffsetDateTime odt = OffsetDateTime.parse("2014-01-11T00:00:00Z");
  1. 日期时间中的Z 代表Zulu,它在ISO 8601 标准中指定UTC 时间(时区偏移为+00:00 小时)。因此,此解决方案也适用于日期时间字符串,例如 2014-01-11-T00:00:00+02:00,其时区偏移量为 +02:00 小时。
  2. 如果你需要OffsetDateTime这个对象中的java.util.Date对象,你可以这样做:
    Date date = Date.from(odt.toInstant());

Trail: Date Time 了解有关 modern date-time API* 的更多信息。

请注意,旧的日期时间 API(java.util 日期时间类型及其格式化 API,SimpleDateFormat)已过时且容易出错。建议完全停止使用它们并切换到java.time API。为了完整起见,我为您提供了一个使用旧版 API 的解决方案。

使用旧版 API:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String args[]) throws ParseException {
        SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-M-d-'T'H:m:sXXX", Locale.ENGLISH);

        SimpleDateFormat sdfOutput = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
        sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));// Change it as required

        Date date = sdfInput.parse("2014-01-11-T00:00:00Z");

        String output = sdfOutput.format(date);
        System.out.println(output);
    }
}

输出:

20140111

* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个Android项目工作并且您的Android API级别仍然不符合Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

  • 是时候有人发布这个 7 年老问题的推荐答案了。非常感谢。
  • 谁给我的评论点赞,谢谢,最好给答案点赞以帮助其他读者找到它。
【解决方案2】:

拿走这个

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormat {

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
        Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");

        SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
        String output = outFormat.format(inDate);

        System.out.println("Date: " + output);

    }
}

【讨论】:

    【解决方案3】:

    看看这个线程在Java中使用Zoulou符号进行日期格式化:

    Converting ISO 8601-compliant String to java.util.Date

    然后使用“yyyyMMdd”格式字符串创建一个新的 SimpleDateFormat。

    【讨论】:

      【解决方案4】:

      这里是@drkunibar 给出的答案的改进版本:

      SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
      inFormat.setTimeZone(TimeZone.getTimeZone("GMT")); // Z denotes UTC in ISO-8601
      Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");
      
      SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
      outFormat.setTimeZone(TimeZone.getTimeZone("...")); // set your timezone explicitly!
      String output = outFormat.format(inDate);
      
      System.out.println("Date: " + output);
      

      请注意,格式 YYYYMMDD 也符合 ISO-8601(所谓的基本日历日期)。您必须问自己的问题是您希望在哪个时区获得输出。如果在 UTC 中,您也必须设置“GMT”。如果不设置时区,您的输出日期可能会与输入 UTC 日期相差一天,具体取决于您的默认系统时区所在的位置(例如,美国比 UTC 晚几个小时,在这种情况下,在 UTC 午夜前一个日历日)。

      【讨论】:

      • 恕我直言?,我推荐使用yyyy-M-d-'T'H:m:sXXX,其中XXX真正代表时区偏移量。模式 yyyy-MM-dd-'T'HH:mm:ss'Z' 仅将 'Z' 指定为字符文字。
      • @ArvindKumarAvinash 我绝对知道 Z 字面量表示零偏移量。因此,我还在输入格式中将时区设置为零以进行必要的补偿。此外,您使用 XXX 的建议肯定是好意,但请注意我在 2014 年发布的旧日期,许多 Java 版本尚未识别新的模式字母 X。所以对于那些旧的 Java 平台来说,整个答案是绝对正确的,并且足够对于明确需要旧 SimpleDateFormat-API 的问题。现在我们有了更好的 API...
      【解决方案5】:

      更新:此答案现已过时。在Answer by Avinash 中查看使用 java.time 的现代解决方案。

      乔达时间

      使用 Joda-Time 2.3 库,这项日期时间工作变得容易得多。

      String input = "2014-01-11T00:00:00Z";  // In standard ISO 8601 format.
      DateTime dateTime = new DateTime( input, DateTimeZone.UTC );  // Parse string into date-time object.
      DateTimeFormatter formatter = ISODateTimeFormat.basicDate();  // Factory to make a formatter.
      String output = formatter.print( dateTime );  // Generate string from date-Time object.
      

      【讨论】:

      • 虽然正确,但我觉得有两点需要解决:(1)问题中提到的模式是2014-01-11-T00:00:00Z而不是2014-01-11T00:00:00Z(2)java.time was released in Mar 2014(在您发布前一个月这个答案),因此您应该使用 java.time API(至少除了 Joda-Time,如果不只是 java.time API)。这是应有的尊重?,正如我多次提到的,我从像你这样的贡献者那里学到了很多与日期时间 API 相关的东西,Andreas,Ole V.V.,Meno Hochschild 等。
      • @ArvindKumarAvinash 对于 (1) 我认为T 之前的连字符很可能是问题中的错字。
      猜你喜欢
      • 2017-01-10
      • 2023-02-16
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多