如何将JDK11中的不同日期格式转换为dd-mm-yyyy格式?[复制]

How to convert different date formats in JDK11 to dd-mm-yyyy format? [duplicate]

提问人:Diksha Goyal 提问时间:5/19/2023 最后编辑:TylerHDiksha Goyal 更新时间:5/23/2023 访问量:154

问:

我有一个用例,其中日期采用以下格式,

  1. 2023-05-09T05:55:07Z
  2. 2023-04-30
  3. 08-05-2023
  4. 2023-05-09 00:00:00
  5. 12月 31, 2021

无论输入格式如何,我都需要将其转换为格式。如何在 JDK11 中转换它?我尝试了不同的库,但没有运气。dd-mm-yyyy

Java java-11 simpledateformat 日期格式 datetimeformatter

评论

4赞 jon hanson 5/19/2023
您是否考虑过为每种格式构造一个 DateTimeFormatter,然后依次尝试每种格式?
1赞 Rogue 5/19/2023
即使在 JS 中,您解析的内容的输入格式也很重要。 只是当前日期,它没有解析那里的任何东西。new Date()
1赞 deHaar 5/19/2023
这个例子非常危险,因为人们无法可靠地推导它是 或 。它们都可以被 解析,但结果会大不相同。08-05-2023MM-dd-uuuudd-MM-uuuuDateTimeFormatter
3赞 Mr. Polywhirl 5/19/2023
不要将包装用于日期。使用 Java 8 中引入的包。请参阅下面的回复。java.utiljava.time
2赞 Basil Bourque 5/21/2023
这个、这个、这个和更多。

答:

2赞 Mr. Polywhirl 5/19/2023 #1

您可以循环访问已知格式并跳过抛出 .DateTimeParseException

注意:如果仅将日期字符串解析为 ,则需要构建格式化程序并指定时间部分是可选的。LocalDateTime

import java.time.LocalDateTime;
import java.time.format.*;
import java.time.temporal.ChronoField;
import java.util.*;

public class DateParser {
    public static void main(String[] args) {
        System.out.println(normalizeDate("2023-05-09T05:55:07Z")); // 2023-05-09
        System.out.println(normalizeDate("2023-04-30")); // 2023-04-30
        System.out.println(normalizeDate("08-05-2023")); // 2023-08-05
        System.out.println(normalizeDate("2023-05-09 00:00:00")); // 2023-05-09
        System.out.println(normalizeDate("31-Dec-2021")); // 2021-12-31
        System.out.println(normalizeDate("")); // null
    }

    public static String normalizeDate(String rawDateTimeString) {
        return Optional.ofNullable(parseDateString(rawDateTimeString))
                .map(displayFormat::format)
                .orElse(null);
    }

    private static LocalDateTime parseDateString(String dateString) {
        for (DateTimeFormatter formatter : knownFormats) {
            try {
                return LocalDateTime.parse(dateString, formatter);
            } catch (DateTimeParseException e) {
                continue;
            }
        }
        return null;
    }

    private static final List<DateTimeFormatter> knownFormats = Arrays.asList(
            DateTimeFormatter.ISO_DATE_TIME,
            dateOnlyFormatter("yyyy-MM-dd"),
            dateOnlyFormatter("MM-dd-yyyy"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            dateOnlyFormatter("dd-MMM-yyyy").withLocale(Locale.ENGLISH));

    private static DateTimeFormatter dateOnlyFormatter(String datePattern) {
        // Credit: https://stackoverflow.com/a/40175568/1762224
        return new DateTimeFormatterBuilder()
                .appendPattern(datePattern)
                .optionalStart()
                .appendPattern(" HH:mm")
                .optionalEnd()
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .toFormatter();
    }

    private static final DateTimeFormatter displayFormat = DateTimeFormatter.ISO_DATE;
}

这是一个修改后的版本,正如 Devin 建议的那样更简单。它完全忽略了时间的概念,在解析时只关注日期。它消除了对该方法的需求(如上所示)。dateOnlyFormatter

import java.time.LocalDate;
import java.time.format.*;
import java.util.*;

public class DateParser {
    public static void main(String[] args) {
        System.out.println(normalizeDate("2023-05-09T05:55:07Z")); // 2023-05-09
        System.out.println(normalizeDate("2023-04-30")); // 2023-04-30
        System.out.println(normalizeDate("08-05-2023")); // 2023-08-05
        System.out.println(normalizeDate("2023-05-09 00:00:00")); // 2023-05-09
        System.out.println(normalizeDate("31-Dec-2021")); // 2021-12-31
        System.out.println(normalizeDate("")); // null
    }

    public static String normalizeDate(String rawDateTimeString) {
        return Optional.ofNullable(parseDateString(rawDateTimeString))
                .map(displayFormat::format)
                .orElse(null);
    }

    private static LocalDate parseDateString(String dateString) {
        for (DateTimeFormatter formatter : knownFormats) {
            try {
                return LocalDate.parse(dateString, formatter);
            } catch (DateTimeParseException e) {
                continue;
            }
        }
        return null;
    }

    private static final List<DateTimeFormatter> knownFormats = Arrays.asList(
            DateTimeFormatter.ISO_DATE_TIME,
            DateTimeFormatter.ofPattern("yyyy-MM-dd"),
            DateTimeFormatter.ofPattern("MM-dd-yyyy"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            DateTimeFormatter.ofPattern("dd-MMM-yyyy").withLocale(Locale.ENGLISH));

    private static final DateTimeFormatter displayFormat = DateTimeFormatter.ISO_DATE;
}

评论

1赞 Mr. Polywhirl 5/19/2023
@user16320675我添加到上面的违规格式化程序中。.withLocale(Locale.ENGLISH)
0赞 Basil Bourque 5/21/2023
很好的答案,但这已经在其他多个现有问题中涉及。
0赞 Basil Bourque 5/21/2023
在实际工作中,区域设置可能需要指定一种区域性,并可能指定一个子区域性。日期时间格式(缩写、标点符号、大写)在不同的英语地区可能会有所不同。
-1赞 DevinJM3 5/19/2023 #2

这种方法简单易懂。以下是 parseDateTime 函数的所有功能:

  1. 设置输出格式
  2. 设置所有可能的输入格式
  3. 循环访问每种输入格式,直到找到正确的格式
  4. 以指定的输出格式返回日期/时间

注意如果传递给函数的 String 不是 5 种指定的输入格式之一,则它将返回 null。这应该可以很容易地看出它是否成功!

如果您需要更多信息来帮助添加更多格式,请参阅 DateTimeFormatter 文档:https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_DATE

import java.time.*;
import java.time.format.DateTimeFormatter;

public class Main {
     public static void main(String[] args) {
        String[] inputDates = {
                "2023-04-30T05:55:07Z",
                "2023-04-30",
                "30-04-2023",
                "2023-04-30 00:00:00",
                "30-Apr-2023"
        };

        for(String date : inputDates)
            System.out.println(date + "\t->\t" + parseDateTime(date));
    }


    private static String parseDateTime(String currentDate){
        //Desired Output Pattern
        DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy");

        //All Possible Input Patterns
        DateTimeFormatter[] formatters = {
            DateTimeFormatter.ISO_LOCAL_DATE,
            DateTimeFormatter.ofPattern("dd-MM-yyyy"),
            DateTimeFormatter.ofPattern("dd-MMM-yyyy"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
        };

        //Iterate over each pattern until it finds the correct one
        for(DateTimeFormatter currFormatter : formatters){
            try{
                return LocalDate.parse(currentDate, currFormatter).format(outputFormat);
            } catch(Exception ignored){
                //Current formatter did not work, so lets try the next one
            }
        }
        return null; // String was not one of those 5 formats
    }
}```

评论

2赞 user16320675 5/19/2023
请注意,解析月份名称是敏感的;这可以代表一个时区,不一定是字面意思LocaleZZ
0赞 Basil Bourque 5/21/2023
切勿在日期时间格式模式中将引号括起来。引号的意思是“期待但忽略此文本”。忽略该文本是不安分的,因为 a 的存在意味着“与 UTC 的偏移量为零小时-分钟-秒”。你丢弃了有价值的信息,却没有回报。我必须对建议数据丢失的解决方案投反对票。ZZ