Подтвердить что ты не робот

Как преобразовать String в Date без знания формата?

У меня проблема. Я пытаюсь преобразовать некоторые строки на сегодняшний день, и я не знаю формат, который приносит дата.

Это может быть как yyyy.mm.dd hh:mm:ss или MM.dd.yy hh:mm:ss и т.д.

Как преобразовать эти строки в Date? Я пробовал это:

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, который как ни странно.

Любые идеи, как я могу правильно форматировать строки на сегодняшний день?

4b9b3361

Ответ 1

Вы не можете!

Если у вас есть дата 2010-08-05, то это может быть либо 5 августа 2010 года, либо 8 мая 2010 года - вам нужно, чтобы узнать формат даты (или, по крайней мере, приоритет одного формата в течение более) чтобы рассказать им обособленно.

Ответ 2

Я согласен с Крагеном в том, что в общем случае нет правильного решения. Однако, если выполняются следующие условия, вы можете использовать следующее решение:

  • У вас есть набор всех возможных форматов

  • Между форматами нет никакой двусмысленности; никакое выражение даты не может быть успешно проанализировано двумя из них.

Рассмотрим следующее решение, которое выполняет итерацию по списку возможных форматов. Это решение использует ThreadLocal, чтобы сделать синтаксический анализ даты эффективным в многопоточной среде (помните, что 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;
    }       
}

Ответ 3

Как отмечалось ранее, вам нужно как минимум иметь упорядоченный список кандидатов на шаблоны. Когда у вас это есть, в Apache DateUtils есть parseDate(String dateString, String[] patterns) который позволяет вам легко попробовать список шаблонов в вашей строке даты и проанализировать его по первому подходящему:

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

Разбирает строку, представляющую дату, пробуя различные парсеры.

Анализ будет пробовать каждый шаблон анализа по очереди. Анализ считается успешным, только если он анализирует всю входную строку. Если шаблоны разбора не совпадают, генерируется ParseException.

Парсер будет снисходительным к анализируемой дате.

Ответ 4

Вот быстрое и грязное решение, основанное на американских форматах даты.

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

Ответ 5

Ваша проблема связана с интернационализацией. Как ответил Краген, вы не можете просто анализировать дату в неизвестном формате. Хотя вы можете сканировать все возможные локали и анализировать что-то, но вы не знаете, правильно ли он разбирался.

Немного i18n фон:

В: Можете ли вы рассказать мне, какой день месяц и год эта дата имеет в виду:

09/11/10?

A: Не зная языка, вы не можете. Это может быть что угодно. 11 сентября в США. 9 ноября в Великобритании. И так далее.

Ответ 6

Если это протокол; определите формат - возможно, ISO, который будет раздражать всех, кроме нас в Швеции...

Если он вводит пользователя; Пусть они устанавливают свой язык. Если вы можете это сделать, покажите синтаксическую дату в полном формате, чтобы пользователь мог ее проверить, например 10 ноября 2009 года.

Ответ 7

Мое единственное предположение, что сначала вы должны собрать статистические данные, чтобы выяснить формат.

Если вам повезет, у вас будет такая дата, как "2010/08/13", которую можно разобрать однозначно

Ответ 8

Этот ответ является копией моего ответа на другой вопрос, который помечен как дубликат этого

Однажды у меня была задача написать код, который будет анализировать строку с датой, где формат даты заранее неизвестен. Т.е. мне пришлось разбирать любой допустимый формат даты. Я написал проект и после этого написал статью, в которой описана идея моей реализации. Вот ссылка на статью: Java 8 пакет java.time: парсинг любой строки на сегодняшний день. Общая идея заключается в том, чтобы записать все шаблоны, которые вы хотите поддерживать, во внешний файл свойств, прочитать их оттуда и попытаться анализировать вашу строку по этим форматам один за другим, пока вы не добьетесь успеха или не исчерпаете форматы. Обратите внимание, что порядок также будет важен, так как некоторые строки могут быть действительными для нескольких форматов (различия США/Европы). Преимущество заключается в том, что вы можете продолжать добавлять/удалять форматы в файл, не меняя код. Таким образом, такой проект также может быть настроен для разных клиентов

Ответ 9

Вот простое решение, которое работает для меня. Это простой метод для анализа даты, передачи аргумента 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;
    }

Ответ 10

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