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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3707485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:45:25  来源:igfitidea点击:

How to convert String to Date without knowing the format?

javadateformat

提问by Shervin Asgari

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:ssor MM.dd.yy hh:mm:ssand so on.

这或许让他们yyyy.mm.dd hh:mm:ssMM.dd.yy hh:mm:ss等。

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 11which is strange to say the least.

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

Any ideas how I can correctly format strings to date?

任何想法如何正确格式化字符串?

采纳答案by Justin

You cant!

你不能!

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

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

回答by Alexander Malakhov

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

如果你很幸运,你会有像“2010/08/13”这样的日期,可以明确地解析

回答by Pawe? Dyda

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.

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

Just a little i18n background:

只是一点 i18n 背景:

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

问:你能告诉我这个日期所指的月份和年份的哪一天:

09/11/10?

10 年 9 月 11 日?

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

答:不知道语言环境,你不能。它可以是任何东西。9 月 11 日在美国。11 月 9 日在英国。等等。

回答by Eyal Schneider

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:

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

  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.

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

  2. 格式之间没有歧义;没有日期表达式可以被其中两个成功解析。

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 SimpleDateFormatisn't thread safe):

考虑以下迭代可能格式列表的解决方案。该解决方案利用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;
    }       
}

回答by oksayt

As noted before, you need to at least have an ordered list of pattern candidates. Once you have that, Apache DateUtilshas 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:

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

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.

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

解析将依次尝试每个解析模式。只有解析了整个输入字符串,解析才被认为是成功的。如果没有匹配的解析模式,则抛出 ParseException。

解析器将对解析日期宽容。

回答by KarlP

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

如果是协议;定义格式 - 也许 ISO 会激怒除瑞典以外的每个人......

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.

如果是用户输入;让他们设置他们的语言环境。如果可以,请以完整格式显示解析的日期,以便用户验证,例如 2009 年 11 月 10 日。

回答by Vignesh Anand

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;
    }

回答by bjoern

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 + "'");
}

回答by Maheshwar Ligade

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;
    }

回答by Michael Gantman

This answer is a copy of my answer to another question that is marked as duplicate of this one

这个答案是我对另一个问题的回答的副本,该问题被标记为这个问题的重复

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

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