Java 如何使用SimpleDataFormat以多种格式解析日期

Java 如何使用SimpleDataFormat以多种格式解析日期,java,parsing,datetime,simpledateformat,Java,Parsing,Datetime,Simpledateformat,我试图解析文档中的一些日期。用户似乎是以类似但不精确的格式输入这些日期的 以下是格式: 9/09 9/2009 09/2009 9/1/2009 9-1-2009 尝试解析所有这些内容的最佳方式是什么?这些似乎是最常见的,但我想让我感到困扰的是,如果我有一个总是在“MM/yyyy”之前捕获的“M/yyy”模式,我是否必须以限制最少到限制最多的方式设置嵌套的try/catch块?看起来,要做到这一点肯定需要大量的代码重复 您需要为每个不同的模式使用不同的SimpleDataFormat对象。也

我试图解析文档中的一些日期。用户似乎是以类似但不精确的格式输入这些日期的

以下是格式:

9/09
9/2009
09/2009
9/1/2009
9-1-2009 

尝试解析所有这些内容的最佳方式是什么?这些似乎是最常见的,但我想让我感到困扰的是,如果我有一个总是在“MM/yyyy”之前捕获的“M/yyy”模式,我是否必须以限制最少到限制最多的方式设置嵌套的try/catch块?看起来,要做到这一点肯定需要大量的代码重复

您需要为每个不同的模式使用不同的
SimpleDataFormat
对象。也就是说,你不需要那么多不同的

数字:对于格式设置,图案字母的数量是最小位数,较短的数字将被零填充到此数量。对于解析,除非需要分隔两个相邻字段,否则将忽略模式字母的数量

因此,您需要以下格式:

9/09
9/2009
09/2009
9/1/2009
9-1-2009 
  • “M/y”
    (包括
    9/09
    9/2009
    09/2009
  • “M/d/y”
    (涵盖
    2009年9月1日
  • “M-d-y”
    (涵盖
    9-1-2009
因此,我的建议是编写一个类似于以下内容的方法(未经测试):

/。。。
List formatStrings=Arrays.asList(“M/y”、“M/d/y”、“M-d-y”);
// ...
Date tryParse(字符串dateString)
{
for(字符串格式字符串:格式字符串)
{
尝试
{
返回新的SimpleDataFormat(formatString).parse(dateString);
}
捕获(异常解析){}
}
返回null;
}

马特的上述方法很好,但请注意,如果使用它来区分格式为
y/M/d
d/M/y
的日期,您将遇到问题。例如,用
y/M/d
初始化的格式化程序将接受类似
01/01/2009
的日期,并返回一个明显不是您想要的日期。我修复了以下问题,但时间有限,我对解决方案不满意,主要原因有两个:

  • 它违反了Josh Bloch的一条准则,特别是“不要使用异常来处理程序流”
  • 如果您需要使用
    getDateFormat()
    方法来处理许多其他日期格式,我可以看到该方法有点像噩梦
  • 如果我必须做一些能够处理很多不同日期格式的东西,并且需要高性能,那么我想我会使用创建一个枚举的方法,将每个不同的日期正则表达式链接到它的格式。然后使用
    MyEnum.values()
    循环遍历枚举并使用
    if(MyEnum.getPattern().matches(date))
    测试,而不是捕获dateformatexception

    也就是说,下面可以处理格式的日期
    'y/M/d''y-M-d''y-M-d''d/M/y''d-M-y''d-M-y''d-M-y'
    ,以及包括时间格式的所有其他变体:

    import java.text.ParseException;
    导入java.text.simpleDataFormat;
    导入java.util.Date;
    公共类DateUtil{
    私有静态最终字符串[]timeFormats={“HH:mm:ss”,“HH:mm”};
    私有静态最终字符串[]日期分隔符={”/“,“-”,“};
    私有静态最终字符串DMY_FORMAT=“dd{sep}MM{sep}yyyy”;
    私有静态最终字符串YMD_FORMAT=“yyyy{sep}MM{sep}dd”;
    私有静态最终字符串ymd_template=“\\d{4}{sep}\\d{2}{sep}\\d{2}.*”;
    私有静态最终字符串dmy_template=“\\d{2}{sep}\\d{2}{sep}\\d{4}.*”;
    公共静态日期stringToDate(字符串输入){
    日期=空;
    字符串dateFormat=getDateFormat(输入);
    如果(dateFormat==null){
    抛出新的IllegalArgumentException(“日期不是接受的格式”+输入);
    }
    for(字符串sep:dateseparator){
    字符串actualDateFormat=patternForSeparator(日期格式,sep);
    //先试试看时间
    for(字符串时间:时间格式){
    日期=tryParse(输入,实际日期格式+“”+时间);
    如果(日期!=null){
    返回日期;
    }
    }
    //不起作用,请尝试不使用时间格式
    日期=tryParse(输入,实际日期格式);
    如果(日期!=null){
    返回日期;
    }
    }
    返回日期;
    }
    私有静态字符串getDateFormat(字符串日期){
    for(字符串sep:dateseparator){
    字符串ymdPattern=patternForSeparator(ymd_模板,sep);
    字符串dmyPattern=patternForSeparator(dmy_模板,sep);
    如果(日期匹配(ymdPattern)){
    返回YMD_格式;
    }
    if(日期匹配(dmyPattern)){
    返回DMY_格式;
    }
    }
    返回null;
    }
    专用静态字符串模式分离器(字符串模板,字符串sep){
    返回模板。替换(“{sep}”,sep);
    }
    私有静态日期tryParse(字符串输入,字符串模式){
    试一试{
    返回新的SimpleDataFormat(模式).parse(输入);
    }
    捕获(异常解析){}
    返回null;
    }
    }
    
    在Apache commons lang类中,我们有一个名为parseDate的方法。我们可以用它来解析日期


    另外,另一个库Joda time也具有截止日期的方法。

    此解决方案在引发异常之前检查所有可能的格式。如果您尝试测试多种日期格式,则此解决方案更方便

    Date extractTimestampInput(String strDate){
        final List<String> dateFormats = Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd");    
    
        for(String format: dateFormats){
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try{
                return sdf.parse(strDate);
            } catch (ParseException e) {
                 //intentionally empty
            }
        }
            throw new IllegalArgumentException("Invalid input for date. Given '"+strDate+"', expecting format yyyy-MM-dd HH:mm:ss.SSS or yyyy-MM-dd.");
    
    }
    
    日期输入(字符串strDate){
    最终列表日期格式=Arrays.asList(“yyyy-MM-dd HH:MM:ss.SSS”,“yyy-MM-dd”);
    用于(字符串格式:日期格式){
    SimpleDataFormat sdf=新的SimpleDataFormat(格式);
    试一试{
    返回sdf.parse(strDate);
    }捕获(解析异常){
    //故意清空
    }
    }
    抛出新的IllegalArgumentException(“日期输入无效。给定
    
    List<SimpleDateFormat> knownPatterns = new ArrayList<SimpleDateFormat>();
    knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
    knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm.ss'Z'"));
    knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
    knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss"));
    knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
    
    for (SimpleDateFormat pattern : knownPatterns) {
        try {
            // Take a try
            return new Date(pattern.parse(candidate).getTime());
    
        } catch (ParseException pe) {
            // Loop on
        }
    }
    System.err.println("No known Date format found: " + candidate);
    return null;
    
    public static boolean isTimeStampValid(String inputString)
    {
        DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd'T'HH:mm:ss.SSSZ]" + "[yyyy-MM-dd]"));
    
        DateTimeFormatter dateTimeFormatter = dateTimeFormatterBuilder.toFormatter();
    
        try {
            dateTimeFormatter.parse(inputString);
            return true;
        } catch (DateTimeParseException e) {
            return false;
        }
    }
    
    private static DateTimeFormatter[] parseFormatters = Stream.of("M/yy", "M/y", "M/d/y", "M-d-y")
            .map(DateTimeFormatter::ofPattern)
            .toArray(DateTimeFormatter[]::new);
    
    public static YearMonth parseYearMonth(String input) {
        for (DateTimeFormatter formatter : parseFormatters) {
            try {
                return YearMonth.parse(input, formatter);
            } catch (DateTimeParseException dtpe) {
                // ignore, try next format
            }
        }
        throw new IllegalArgumentException("Could not parse " + input);
    }
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.apache.commons.lang.time.DateUtils;
    
    public class DateUtility {
    
        public static Date parseDate(String inputDate) {
    
            Date outputDate = null;
            String[] possibleDateFormats =
                  {
                        "yyyy.MM.dd G 'at' HH:mm:ss z",
                        "EEE, MMM d, ''yy",
                        "h:mm a",
                        "hh 'o''clock' a, zzzz",
                        "K:mm a, z",
                        "yyyyy.MMMMM.dd GGG hh:mm aaa",
                        "EEE, d MMM yyyy HH:mm:ss Z",
                        "yyMMddHHmmssZ",
                        "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
                        "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
                        "YYYY-'W'ww-u",
                        "EEE, dd MMM yyyy HH:mm:ss z", 
                        "EEE, dd MMM yyyy HH:mm zzzz",
                        "yyyy-MM-dd'T'HH:mm:ssZ",
                        "yyyy-MM-dd'T'HH:mm:ss.SSSzzzz", 
                        "yyyy-MM-dd'T'HH:mm:sszzzz",
                        "yyyy-MM-dd'T'HH:mm:ss z",
                        "yyyy-MM-dd'T'HH:mm:ssz", 
                        "yyyy-MM-dd'T'HH:mm:ss",
                        "yyyy-MM-dd'T'HHmmss.SSSz",
                        "yyyy-MM-dd",
                        "yyyyMMdd",
                        "dd/MM/yy",
                        "dd/MM/yyyy"
                  };
    
            try {
    
                outputDate = DateUtils.parseDate(inputDate, possibleDateFormats);
                System.out.println("inputDate ==> " + inputDate + ", outputDate ==> " + outputDate);
    
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            return outputDate;
    
        }
    
        public static String formatDate(Date date, String requiredDateFormat) {
            SimpleDateFormat df = new SimpleDateFormat(requiredDateFormat);
            String outputDateFormatted = df.format(date);
            return outputDateFormatted;
        }
    
        public static void main(String[] args) {
    
            DateUtility.parseDate("20181118");
            DateUtility.parseDate("2018-11-18");
            DateUtility.parseDate("18/11/18");
            DateUtility.parseDate("18/11/2018");
            DateUtility.parseDate("2018.11.18 AD at 12:08:56 PDT");
            System.out.println("");
            DateUtility.parseDate("Wed, Nov 18, '18");
            DateUtility.parseDate("12:08 PM");
            DateUtility.parseDate("12 o'clock PM, Pacific Daylight Time");
            DateUtility.parseDate("0:08 PM, PDT");
            DateUtility.parseDate("02018.Nov.18 AD 12:08 PM");
            System.out.println("");
            DateUtility.parseDate("Wed, 18 Nov 2018 12:08:56 -0700");
            DateUtility.parseDate("181118120856-0700");
            DateUtility.parseDate("2018-11-18T12:08:56.235-0700");
            DateUtility.parseDate("2018-11-18T12:08:56.235-07:00");
            DateUtility.parseDate("2018-W27-3");
        }
    
    }
    
    import java.text.SimpleDateFormat
    import org.apache.commons.lang.time.DateUtils
    
    object MultiDataFormat {
      def main(args: Array[String]) {
    
    val dates =Array("2015-10-31","26/12/2015","19-10-2016")
    
    val possibleDateFormats:Array[String] = Array("yyyy-MM-dd","dd/MM/yyyy","dd-MM-yyyy")
    
    val sdf =  new SimpleDateFormat("yyyy-MM-dd") //change it as per the requirement
      for (date<-dates) {
        val outputDate = DateUtils.parseDateStrictly(date, possibleDateFormats)
        System.out.println("inputDate ==> " + date + ", outputDate ==> " +outputDate + " " + sdf.format(outputDate) )
      }
    }
    
    
    import java.text.SimpleDateFormat;
    import java.time.LocalDateTime;
    import java.time.ZoneOffset;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.temporal.TemporalAccessor;
    import java.util.Date;
    import java.util.TimeZone;
    
    public class DateTimeFormatTest {
    
        public static void main(String[] args) {
    
            String pattern = "[yyyy-MM-dd[['T'][ ]HH:mm:ss[.SSSSSSSz][.SSS[XXX][X]]]]";
            String timeSample = "2018-05-04T13:49:01.7047141Z";
            SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
            TemporalAccessor accessor = formatter.parse(timeSample);
            ZonedDateTime zTime = LocalDateTime.from(accessor).atZone(ZoneOffset.UTC);
    
            Date date=new Date(zTime.toEpochSecond()*1000);
            simpleDateFormatter.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
            System.out.println(simpleDateFormatter.format(date));       
        }
    }
    
    private String getDate(String anyDateFormattedString) {
        @SuppressWarnings("deprecation")
        Date date = new Date(anyDateFormattedString);
        SimpleDateFormat dateFormat = new SimpleDateFormat(yourDesiredDateFormat);
            String convertedDate = dateFormat.format(date);
        return convertedDate;
    }
    
    fun parseTime(time: String?): Long {
        val longRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}.\\d{3}[Z]\$"
        val shortRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}Z\$"
    
        val longDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssXXX")
        val shortDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
    
        return when {
            Pattern.matches(longRegex, time) -> longDateFormat.parse(time).time
            Pattern.matches(shortRegex, time) -> shortDateFormat.parse(time).time
            else -> throw InvalidParamsException(INVALID_TIME_MESSAGE, null)
        }
    }
    
    final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
    dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
        .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);