如何在不知道格式的情况下将字符串转换为日期?

发布于 2024-09-18 16:06:05 字数 494 浏览 3 评论 0原文

我有一个问题。我正在尝试将一些字符串转换为日期,但我不知道日期到达的格式。

它可能为 yyyy.mm.dd hh:mm:ssMM.dd.yy hh:mm:ss 等等。

如何将这些字符串转换为日期? 我尝试了这个:

DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
Date d = (Date)formatter.parse(someDate);

但是当我打印出 someDate 时,它​​打印出来是这样的: 2010-08-05 12:42:48.638 CEST 这意味着 yyyy.mm.dd hh:mm:ss ,但是当我运行上面的代码,日期对象现在变成了 Sat Jan 31 00:42:48 CET 11 至少可以说很奇怪。

到目前为止,我有什么想法可以正确格式化字符串吗?

I have a problem. I am trying to convert some strings to date, and I don't know the format the date is arriving.

It might come as yyyy.mm.dd hh:mm:ss or MM.dd.yy hh:mm:ss and so on.

How can I convert these strings to Date?
I tried this:

DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
Date d = (Date)formatter.parse(someDate);

But when I printed out someDate it printed out like this: 2010-08-05 12:42:48.638 CEST which means yyyy.mm.dd hh:mm:ss, however when I ran the above code, the date object now became Sat Jan 31 00:42:48 CET 11 which is strange to say the least.

Any ideas how I can correctly format strings to date?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

美人如玉 2024-09-25 16:06:06

如前所述,您至少需要有一个候选模式的有序列表。一旦你有了这个, Apache DateUtils 有一个 parseDate(String dateString, String[]patterns) 方法,可让您轻松尝试日期字符串上的模式列表,并按第一个匹配的模式对其进行解析:

public static Date parseDate(String str,
                         String[] parsePatterns)
                  throws ParseException

通过尝试各种不同的解析器来解析表示日期的字符串。

解析将依次尝试每种解析模式。仅当解析整个输入字符串时,解析才被视为成功。如果没有匹配的解析模式,则会抛出 ParseException。

解析器对解析的日期会比较宽松。

As noted before, you need to at least have an ordered list of pattern candidates. Once you have that, Apache DateUtils has a parseDate(String dateString, String[] patterns) method that lets you easily try out a list of patterns on your date string, and parse it by the first one that matches:

public static Date parseDate(String str,
                         String[] parsePatterns)
                  throws ParseException

Parses a string representing a date by trying a variety of different parsers.

The parse will try each parse pattern in turn. A parse is only deemed successful if it parses the whole of the input string. If no parse patterns match, a ParseException is thrown.

The parser will be lenient toward the parsed date.

月朦胧 2024-09-25 16:06:06

这是一个基于美国日期格式的快速而肮脏的解决方案。

public Date parseDate(String strDate) throws Exception
{
    if (strDate != null && !strDate.isEmpty())
    {
        SimpleDateFormat[] formats =
                new SimpleDateFormat[] {new SimpleDateFormat("MM-dd-yyyy"), new SimpleDateFormat("yyyyMMdd"),
                        new SimpleDateFormat("MM/dd/yyyy")};

        Date parsedDate = null;

        for (int i = 0; i < formats.length; i++)
        {
            try
            {
                parsedDate = formats[i].parse(strDate);
                return parsedDate;
            }
            catch (ParseException e)
            {
                continue;
            }
        }
    }
    throw new Exception("Unknown date format: '" + strDate + "'");
}

Here is a quick and dirty solution based on american date formats.

public Date parseDate(String strDate) throws Exception
{
    if (strDate != null && !strDate.isEmpty())
    {
        SimpleDateFormat[] formats =
                new SimpleDateFormat[] {new SimpleDateFormat("MM-dd-yyyy"), new SimpleDateFormat("yyyyMMdd"),
                        new SimpleDateFormat("MM/dd/yyyy")};

        Date parsedDate = null;

        for (int i = 0; i < formats.length; i++)
        {
            try
            {
                parsedDate = formats[i].parse(strDate);
                return parsedDate;
            }
            catch (ParseException e)
            {
                continue;
            }
        }
    }
    throw new Exception("Unknown date format: '" + strDate + "'");
}
鹿港巷口少年归 2024-09-25 16:06:06

您的问题与国际化有关。正如克拉根回答的那样,你不能只解析未知格式的日期。虽然您可以扫描所有可能的语言环境并解析某些内容,但您不知道它是否已正确解析。

简单介绍一下 i18n 背景:

问:您能告诉我这个日期指的是哪一年、哪一天吗:

09/11/10?

答:如果不知道区域设置,你就不能。它可以是任何东西。 9 月 11 日在美国。 11 月 9 日,英国。等等。

Your problem is related to Internationalization. As Kragen answered, you can't just parse date in unknown format. Although you can scan all possible locales and parse something, but you wouldn't know if it was parsed correctly.

Just a little i18n background:

Q: Can you tell me what day month and year this date is referring to:

09/11/10?

A: Without knowing the locale, you can't. It could be anything. September, 11th in USA. November, 9th in Great Britain. And so on.

落日海湾 2024-09-25 16:06:06

我曾经有一个任务要编写一个代码,该代码可以将字符串解析为日期,其中日期格式事先未知。即我必须解析任何有效的日期格式。我写了一个项目,然后写了一篇文章来描述我的实现背后的想法。以下是文章的链接: Java 8 java.time 包:解析迄今为止的任何字符串。一般想法是将您希望支持的所有模式写入外部属性文件中并从那里读取它们,并尝试按这些格式一一解析您的字符串,直到成功或用完格式为止。请注意,顺序也很重要,因为某些字符串可能对多种格式有效(美国/欧洲的差异)。优点是您可以不断向文件添加/删除格式,而无需更改代码。所以这样的项目也可以为不同的客户定制

I once had a task to write a code that would parse a String to date where date format was not known in advance. I.e. I had to parse any valid date format. I wrote a project and after that I wrote an article that described the idea behind my implementation. Here is the link to the article: Java 8 java.time package: parsing any string to date. General Idea is to write all the patterns that you wish to support into external properties file and read them from there and try to parse your String by those formats one by one until you succeed or run out of formats. Note that the order also would be important as some Strings may be valid for several formats (US/European differences). Advantage is that you can keep adding/removing formats to the file without changing your code. So such project could also be customized for different customers

多像笑话 2024-09-25 16:06:06

如果它是一个协议;定义格式 - 也许 ISO 会激怒除我们瑞典以外的所有人......

如果它是由用户输入的;让他们设置他们的区域设置。如果可以的话,以完整格式显示解析后的日期,以便用户可以验证它,例如 2009 年 11 月 10 日。

If its a protocol; define the format - perhaps ISO that will irritate everyone except us in sweden...

If it input from users; Let them set their locale. If you can do it, show the parsed date in full format so the user can verify it, like November 10, 2009.

忘东忘西忘不掉你 2024-09-25 16:06:06

我唯一的猜测是,您应该首先收集一些统计数据来找出格式。

如果幸运的话,您将拥有像“2010/08/13”这样的日期,可以明确地解析它

My only guess, is that you should gather some statistics first to figure out the format.

If you're lucky, you will have date like "2010/08/13" which can be parsed unambiguously

半岛未凉 2024-09-25 16:06:06

我创建了一个实用程序来尝试解析一些常见的日期格式。
它会尝试检查哪个数字大于 12,否则如果两者都小于 12,它会优先选择用户定义的布尔值 PreferredMonthFirst,并根据该值在 MM/dd/yyyydd/ 之间进行选择MM/yyyy

它还接受prefer24HourTime 布尔值来解析时间。

我没有使用列表并迭代它并尝试解析它并尝试捕获异常,因为异常的成本更高。因此,根据分隔符和长度,我尝试找到日期格式。

您可以在测试用例中找到用法。

https://github.com/rajat-g/DateParser

I created a utility that tries to parse some common date formats.
It tries to check which digit is greater than 12 or else if both are less than 12 it prefers user-defined boolean preferMonthFirst based on which it will choose between MM/dd/yyyy or dd/MM/yyyy

It also accepts prefer24HourTime boolean for parsing time.

I did not use the list and iterate over it and try to parse it and tried to catch exception because Exceptions are costlier. So based on separator and length I tried to find the date format.

You can find usages in the test cases.

https://github.com/rajat-g/DateParser

零崎曲识 2024-09-25 16:06:06

这是简单的解决方案,对我有用。
这是解析日期的简单方法,将字符串作为参数传递&以您想要的任何格式解析它。

String dateToConvert(String date) {
        String strDate = "";
        try {
            //create SimpleDateFormat object with source string date format
            DateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd");

            //parse the string into Date object
            Date d = sdfSource.parse(date);
            LocalLog.e(LOG_TAG, d.toString());
            //create SimpleDateFormat object with desired date format
            SimpleDateFormat sdfDestination = new SimpleDateFormat(AppConstants.UNIVERSAL_DATE_FORMAT);

            //parse the date into another format
            strDate = sdfDestination.format(d);

            LocalLog.e(LOG_TAG, strDate);

        } catch (ParseException pe) {
            System.out.println("Parse Exception : " + pe);
        }
        return strDate;
    }

Here is the simple solution, which is worked for me.
This is the simple method to parse the date, pass the String as argument & parse it in any format those you want.

String dateToConvert(String date) {
        String strDate = "";
        try {
            //create SimpleDateFormat object with source string date format
            DateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd");

            //parse the string into Date object
            Date d = sdfSource.parse(date);
            LocalLog.e(LOG_TAG, d.toString());
            //create SimpleDateFormat object with desired date format
            SimpleDateFormat sdfDestination = new SimpleDateFormat(AppConstants.UNIVERSAL_DATE_FORMAT);

            //parse the date into another format
            strDate = sdfDestination.format(d);

            LocalLog.e(LOG_TAG, strDate);

        } catch (ParseException pe) {
            System.out.println("Parse Exception : " + pe);
        }
        return strDate;
    }
睫毛溺水了 2024-09-25 16:06:06
public  String compareDate( PaymentTxnRequest request ) throws ParseException { 
        Date debitDate= request.getPaymentTxn().getCrValDt();
        Date now = new Date();
        String response="";
        SimpleDateFormat sdfDate = new SimpleDateFormat("dd/MM/yyyy");
        String strCurrDate = sdfDate.format(now);
        String strDebitDate = sdfDate.format(debitDate);
        System.out.println("Current Date: " + strCurrDate);
        Date currentDate =  new SimpleDateFormat("dd/MM/yyyy").parse(strCurrDate);
        Date txnDate =  new SimpleDateFormat("dd/MM/yyyy").parse(strDebitDate);
        System.out.println("C -> "+currentDate);
        System.out.println("C -> "+txnDate); 
         if (txnDate!=null){
         if (currentDate.equals(txnDate))
         {
             System.out.println("Valid Txn");
             response="valid";
         }
         if (currentDate.after(txnDate))
         {
            System.out.println("--> Not  Valid TXN Past");   
            response="notValid";
         }
        if (currentDateenter code here.before(txnDate)){
            System.out.println("Future Valid TXn");
             response="future";
        }
     }
        return response;
    }
public  String compareDate( PaymentTxnRequest request ) throws ParseException { 
        Date debitDate= request.getPaymentTxn().getCrValDt();
        Date now = new Date();
        String response="";
        SimpleDateFormat sdfDate = new SimpleDateFormat("dd/MM/yyyy");
        String strCurrDate = sdfDate.format(now);
        String strDebitDate = sdfDate.format(debitDate);
        System.out.println("Current Date: " + strCurrDate);
        Date currentDate =  new SimpleDateFormat("dd/MM/yyyy").parse(strCurrDate);
        Date txnDate =  new SimpleDateFormat("dd/MM/yyyy").parse(strDebitDate);
        System.out.println("C -> "+currentDate);
        System.out.println("C -> "+txnDate); 
         if (txnDate!=null){
         if (currentDate.equals(txnDate))
         {
             System.out.println("Valid Txn");
             response="valid";
         }
         if (currentDate.after(txnDate))
         {
            System.out.println("--> Not  Valid TXN Past");   
            response="notValid";
         }
        if (currentDateenter code here.before(txnDate)){
            System.out.println("Future Valid TXn");
             response="future";
        }
     }
        return response;
    }
浮光之海 2024-09-25 16:06:05

你不能!

如果您的日期为 2010-08-05,那么它可以是 2010 年 8 月 5 日或 2010 年 5 月 8 日 - 您需要知道日期格式(或者至少优先考虑一种格式)来区分它们。

You cant!

If you have the date 2010-08-05 then it can be either 5th August 2010, or 8th May 2010 - you need to know the date format (or at least prioritise one format over the over) to tell them apart.

固执像三岁 2024-09-25 16:06:05

我同意克拉根的观点,在一般情况下没有正确的解决方案。但是,如果满足以下条件,您可以使用以下解决方案:

  1. 您有一组所有可能的格式

  2. 格式之间没有歧义;其中两个都无法成功解析任何日期表达式。

考虑以下解决方案,该解决方案迭代可能的格式列表。此解决方案利用 ThreadLocal,为了在多线程环境中提高日期解析效率(请记住 SimpleDateFormat 不是线程安全的):

public class FlexibleDateParser {
    private List<ThreadLocal<SimpleDateFormat>> threadLocals = new  ArrayList<ThreadLocal<SimpleDateFormat>>();

    public FlexibleDateParser(List<String> formats, final TimeZone tz){
        threadLocals.clear();
        for (final String format : formats) {
            ThreadLocal<SimpleDateFormat> dateFormatTL = new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    SimpleDateFormat sdf = new SimpleDateFormat(format);
                    sdf.setTimeZone(tz); 
                    sdf.setLenient(false);
                    return sdf;
                }
            };
            threadLocals.add(dateFormatTL);
        }       
    }

    public Date parseDate(String dateStr) throws ParseException {
        for (ThreadLocal<SimpleDateFormat> tl : threadLocals) {
            SimpleDateFormat sdf = tl.get();
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                // Ignore and try next date parser
            }
        }
        // All parsers failed
        return null;
    }       
}

I agree with Kragen that in the general case there is no correct solution. However, if the following conditions hold, you may use the solution below:

  1. You have a set of all possible formats

  2. There is no ambiguity between the formats; no date expression can be successfully parsed by two of them.

Consider the following solution which iterates over a list of possible formats. This solution makes use of ThreadLocal, in order to make date parsing efficient in a multi-threaded environment (remember that SimpleDateFormat isn't thread safe):

public class FlexibleDateParser {
    private List<ThreadLocal<SimpleDateFormat>> threadLocals = new  ArrayList<ThreadLocal<SimpleDateFormat>>();

    public FlexibleDateParser(List<String> formats, final TimeZone tz){
        threadLocals.clear();
        for (final String format : formats) {
            ThreadLocal<SimpleDateFormat> dateFormatTL = new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    SimpleDateFormat sdf = new SimpleDateFormat(format);
                    sdf.setTimeZone(tz); 
                    sdf.setLenient(false);
                    return sdf;
                }
            };
            threadLocals.add(dateFormatTL);
        }       
    }

    public Date parseDate(String dateStr) throws ParseException {
        for (ThreadLocal<SimpleDateFormat> tl : threadLocals) {
            SimpleDateFormat sdf = tl.get();
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                // Ignore and try next date parser
            }
        }
        // All parsers failed
        return null;
    }       
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文