繁体   English   中英

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

[英]How to convert String to Date without knowing the 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 yyyy.mm.dd hh:mm:ss ,但是当我运行上面的代码时,日期对象现在变成了Sat Jan 31 00:42:48 CET 11至少可以说很奇怪。

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

你不能!

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

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

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

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

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

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

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

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

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

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

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

只是一点 i18n 背景:

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

10 年 9 月 11 日?

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM