如何在不知道格式的情况下将String转换为Date?

时间:2010-09-14 09:12:54

标签: java date format

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

它可能会显示为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,但是当我运行上面的代码时,日期对象现在变为{{1至少可以说是奇怪的。

任何想法如何才能正确格式化字符串到目前为止?

10 个答案:

答案 0 :(得分:45)

你不能!

如果您的日期为2010-08-05,则可能是2010年8月5日或2010年5月8日 - 您需要了解日期格式(或至少优先考虑一种格式告诉他们分开。

答案 1 :(得分:11)

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

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

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

  3. 考虑以下解决方案,它迭代可能的格式列表。此解决方案使用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;
        }       
    }
    

答案 2 :(得分:7)

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

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

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

     

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

     

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

答案 3 :(得分:5)

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

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

答案 4 :(得分:4)

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

只是一点点i18n背景:

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

09/11/10?

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

我唯一的猜测是,你应该首先收集一些统计数据来确定格式。

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:-1)

这是一个简单的解决方案,对我有用。 这是解析日期的简单方法,将String作为参数传递。以任何你想要的格式解析它。

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

答案 9 :(得分:-2)

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