如何在java中获取给定的日期字符串格式(模式)?

时间:2011-09-28 06:38:10

标签: java date format

我想获得给定日期字符串的格式。

示例:我有一个类似2011-09-27T07:04:21.97-05:00的字符串,此字符串的日期格式为yyyy-MM-dd'T'HH:mm:ss.SSS

这里我希望在将字符串(2011-09-27T07:04:21.97-05:00)传递给将返回格式(yyyy-MM-dd'T'HH:mm:ss.SSS)的方法时找出这种日期格式,然后我将根据以下格式设置我的给定日期字符串我的要求(like yy-mm--dd or mm/dd/yyyy)。

任何人都可以告诉我如何实现它?

10 个答案:

答案 0 :(得分:43)

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NewClass {

    private static final String[] formats = { 
                "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'HH:mm:ss.SSS'Z'",
                "yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd HH:mm:ss", 
                "MM/dd/yyyy HH:mm:ss",        "MM/dd/yyyy'T'HH:mm:ss.SSS'Z'", 
                "MM/dd/yyyy'T'HH:mm:ss.SSSZ", "MM/dd/yyyy'T'HH:mm:ss.SSS", 
                "MM/dd/yyyy'T'HH:mm:ssZ",     "MM/dd/yyyy'T'HH:mm:ss", 
                "yyyy:MM:dd HH:mm:ss",        "yyyyMMdd", };

        /*
         * @param args
         */
    public static void main(String[] args) {
        String yyyyMMdd = "20110917";   
        parse(yyyyMMdd);
    }

    public static void parse(String d) {
        if (d != null) {
            for (String parse : formats) {
                SimpleDateFormat sdf = new SimpleDateFormat(parse);
                try {
                    sdf.parse(d);
                    System.out.println("Printing the value of " + parse);
                } catch (ParseException e) {

                }
            }
        }
    }
}

答案 1 :(得分:6)

你可以这样做,我不知道好不好但是试试这个

首先创建SimpleDateFormat对象

SimpleDateFormt sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");

现在检查日期时是否会以此格式解析,然后根据您的格式进行更改

try{
     Date date = sdf.parse(yourdate);
     sdf.applyPattern("yy-mm--dd or mm/dd/yyyy");
     String dateformat = sdf.format(date);
}catch(Exception ex) { // here forgot the exact exception class Parse exception was used
    // do something here
}

更新帖子:

Returning a date format from an unknown format of date string in java

How to convert String to Date without knowing the format?

Parse any date in Java

答案 2 :(得分:3)

我认为您应该尝试使用某些预定义模式解析输入字符串。有效的是你需要的那个。请记住,某些模式非常棘手。

01.12.12是2012年12月1日在欧洲但2012年1月12日在美国。也可能是2001年12月12日。

答案 3 :(得分:2)

如果我理解正确,您希望使用DateFormat.parse()任意字符串(即您不知道的格式的字符串)解析为日期?然后你必须处理如何处理01-02-03(2003年1月2日?2003年2月1日等等)的问题。

您至少应该知道关于预期格式的某些内容,例如为您的输入选择多种预定义格式。

答案 4 :(得分:2)

Madhu的代码可以锻炼,但是会出现一些性能问题,因为每个失败案例都会引发异常。 我认为我们需要找到调节器表达式解决方案,以便从给定的日期字符串中找到模式。

您可以在以下链接中找到所有最常见的日期和时间格式的表达式

http://regexlib.com/DisplayPatterns.aspx?cattabindex=4&categoryId=5&AspxAutoDetectCookieSupport=1

答案 5 :(得分:0)

您需要获取初始日期字符串并将其转换为日期对象并传递转换后的日期对象并将其格式化为所需的字符串。

答案 6 :(得分:0)

您可以尝试dateparser

它可以自动识别任何字符串,并将其解析为日期日历 LocalDateTime OffsetDateTime 正确,快速(1us~1.5us)。

它不基于任何natural language analyzerSimpleDateFormatregex.Pattern

有了它,您不必准备任何适当的模式,例如yyyy-MM-dd'T'HH:mm:ss'Z'MM/dd/yyyy HH:mm:ss等:

Date date = DateParserUtils.parseDate("2015-04-29T10:15:00.500+0000");
Calendar calendar = DateParserUtils.parseCalendar("2015-04-29T10:15:00.500Z");
LocalDateTime dateTime = DateParserUtils.parseDateTime("2015-04-29 10:15:00.500 +00:00");

它的性能优于循环尝试多个SimpleDateFormat

请尽情享受。

答案 7 :(得分:0)

这是一种通用解决方案,无需事先知道日期模式就可以确定模式,而无需为所有格式调用SimpleDateFormat的parse方法。您可以使用正则表达式从日期字符串值中获取任何日期模式。

package com.utility.utils.modelmapper.datetime;

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

public class DateParser {
    private static final Map<String, String> DATE_FORMAT_REGEXPS = new HashMap<String, String>() {
        {
            put("^\\d{8}$", "yyyyMMdd");
            put("^\\d{12}$", "yyyyMMddHHmm");
            put("^\\d{8}\\s\\d{4}$", "yyyyMMdd HHmm");
            put("^\\d{14}$", "yyyyMMddHHmmss");
            put("^\\d{8}\\s\\d{6}$", "yyyyMMdd HHmmss");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}$", "dd-MM-yyyy");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}$", "yyyy-MM-dd");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}$", "MM/dd/yyyy");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}$", "yyyy/MM/dd");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}$", "dd MMM yyyy");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}$", "dd MMMM yyyy");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}$", "dd-MM-yyyy HH:mm");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy-MM-dd HH:mm");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}$", "MM/dd/yyyy HH:mm");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy/MM/dd HH:mm");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMM yyyy HH:mm");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMMM yyyy HH:mm");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd-MM-yyyy HH:mm:ss");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy-MM-dd HH:mm:ss");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "MM/dd/yyyy HH:mm:ss");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy/MM/dd HH:mm:ss");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMM yyyy HH:mm:ss");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMMM yyyy HH:mm:ss");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{2}:\\d{2}\\.\\d{2}[-+]\\d{2}:\\d{2}$", "yyyy-MM-dd'T'HH:mm:ss.SSS");
        }
    };

    /**
     * To Determine the pattern by the string date value
     * 
     * @param dateString
     * @return The matching SimpleDateFormat pattern, or null if format is unknown.
     */
    public static String determineDateFormat(String dateString) {
        for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
            if (dateString.matches(regexp) || dateString.toLowerCase().matches(regexp)) {
                return DATE_FORMAT_REGEXPS.get(regexp);
            }
        }
        return null;
    }

    public static void main(String[] args) {
        parse("2011-09-27T07:04:21.97-05:00"); //here is your value
        parse("20110917");
        parse("01/02/2018");
        parse("02-01-2018 06:07:59");
        parse("02 January 2018");
    }

    public static void parse(String value) {
        if (value != null) {
            String format = determineDateFormat(value);
            if (format != null) {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                try {
                    Date date = sdf.parse(value);
                    System.out.println(String.format("Format : %s | Value : %s | Parsed Date : %s", value, date, format));
                } catch (ParseException e) {
                    // Failed the execution
                }
            }
        }
    }
}

该类的控制台输出:

Format : 2011-09-27T07:04:21.97-05:00 | Value : Tue Sep 27 07:04:21 LINT 2011 | Parsed Date : yyyy-MM-dd'T'HH:mm:ss.SSS
Format : 20110917 | Value : Sat Sep 17 00:00:00 LINT 2011 | Parsed Date : yyyyMMdd
Format : 01/02/2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : MM/dd/yyyy
Format : 02-01-2018 06:07:59 | Value : Tue Jan 02 06:07:59 LINT 2018 | Parsed Date : dd-MM-yyyy HH:mm:ss
Format : 02 January 2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : dd MMMM yyyy

也许我错过了一些日期时间模式,但是为此,应该在地图中添加正确的正则表达式模式。

答案 8 :(得分:0)

java.time及其预定义的格式化程序

我们不能仅对任何日期时间格式执行此操作。它们有成千上万,我们不知道它们全都有(明天有人会发明一个新的),有些看起来相似,以至于我们不知道我们有什么。

我建议,出于大多数目的,您需要解析字符串,但无需了解格式格式。在很多情况下,包括您问题中的示例2011-09-27T07:04:21.97-05:00,我们都无需指定模式(您的字符串与DateTimeFormatter.ISO_OFFSET_DATE_TIME匹配)。

自从Java 8于2014年问世以来(即使仍使用Java 6或7),请使用现代Java日期和时间API java.time进行日期和时间工作。

我正在为我们要满足的格式定义一个格式化程序数组。请替换您自己的设置。

private static final DateTimeFormatter[] formatters = {
        DateTimeFormatter.ISO_OFFSET_DATE_TIME,
        DateTimeFormatter.RFC_1123_DATE_TIME,
        new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
                .toFormatter(),
        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withLocale(Locale.US),
        DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm")
                .withZone(ZoneId.of("America/Los_Angeles"))
};

以下方法依次尝试格式化程序,直到一种有效为止:

private static OffsetDateTime parse(String dateTimeString) {
    for (DateTimeFormatter formatter : formatters) {
        try {
            return ZonedDateTime.parse(dateTimeString, formatter)
                    .toOffsetDateTime();
        } catch (DateTimeParseException dtpe) {
            // Ignore, try next formatter
        }
    }
    throw new IllegalArgumentException("String " + dateTimeString + " could not be parsed");
} 

让我们尝试一些不同的字符串:

    String[] dateTimeStrings = {
            "2011-09-27T07:04:21.97-05:00",
            "20110917",
            "2012-07-04",
            "12/27/2014 23:45",
            "Mon, 12 Nov 2018 01:32:10 GMT",
            "July 29, 2015 at 10:19:36 AM EDT",
    };
    
    for (String dts : dateTimeStrings) {
        try {
            System.out.format("%32s -> %s%n", dts, parse(dts));
        } catch (IllegalArgumentException iae) {
            System.out.format("%32s -> %s%n", dts, iae);
        }
    }

输出为:

    2011-09-27T07:04:21.97-05:00 -> 2011-09-27T07:04:21.970-05:00
                        20110917 -> java.lang.IllegalArgumentException: String 20110917 could not be parsed
                      2012-07-04 -> 2012-07-04T00:00Z
                12/27/2014 23:45 -> 2014-12-27T23:45-08:00
   Mon, 12 Nov 2018 01:32:10 GMT -> 2018-11-12T01:32:10Z
July 29, 2015 at 10:19:36 AM EDT -> 2015-07-29T10:19:36-04:00

其他选项

多种格式的日期和时间解析技术包括:

  • 尝试一下字符串来确定其格式,并根据该格式使用适当的格式化程序。如果您只有几种格式,那么这是最合适的选择,尽管Vinit Solanki的回答显示了许多格式的精巧版本。
  • 在格式模式字符串中使用可选部分。例如,[uuuu][uu]将解析四位数或两位数的年份(2021或仅21)。
  • 依次尝试几个格式化程序,如我上面的代码所示。如果您确实需要了解模式,请使用模式数组而不是格式化程序数组。
  • 也要求字符串的提供者提供格式模式字符串。但是,这并不总是听起来那么简单。

当心歧义。经典示例是MM-dd-yyyydd-MM-yyyy这两种格式。如果我们得到一个字符串03-09-2020,则无法判断是3月9日还是9月3日。更糟糕的是,02-05-07可能是yy-MM-dddd-MM-yyMM-dd-yy,甚至还有更多可能性。因此,请确保您没有包含两个(或多个)格式化程序,这些格式化程序可能会将同一字符串解析为不同的结果。

链接

答案 9 :(得分:-3)

HH:mm:ss.SSS => ([0-2]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(.)([0-9]{1,3})

yyyy-mm-dd => ([0-9]{4})(-)([0-1]{1,}[0-9]{1,})(-)([0-3]{1,}[0-9]{1,})