Как получить заданный формат строки даты (шаблон) в Java?

Я хочу получить формат заданной строки даты.

Пример: у меня есть строка как 2011-09-27T07:04:21.97-05:00 и формат даты этой строки yyyy-MM-dd'T'HH:mm:ss.SSS,

Здесь я хочу узнать этот формат даты, когда я передаю строку (2011-09-27T07:04:21.97-05:00) к методу, который будет возвращать формат (yyyy-MM-dd'T'HH:mm:ss.SSS), позже я отформатирую данную строку даты в соответствии с моим требованием (like yy-mm--dd or mm/dd/yyyy).

Может кто-нибудь сказать мне, как я могу добиться этого?

7 ответов

Решение
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NewClass {

    private static final String[] formats = { 
                "yyyy-MM-dd'T'HH:mm:ss'Z'",   "yyyy-MM-dd'T'HH:mm:ssZ",
                "yyyy-MM-dd'T'HH:mm:ss",      "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
                "yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd HH:mm:ss", 
                "MM/dd/yyyy HH:mm:ss",        "MM/dd/yyyy'T'HH:mm:ss.SSS'Z'", 
                "MM/dd/yyyy'T'HH:mm:ss.SSSZ", "MM/dd/yyyy'T'HH:mm:ss.SSS", 
                "MM/dd/yyyy'T'HH:mm:ssZ",     "MM/dd/yyyy'T'HH:mm:ss", 
                "yyyy:MM:dd HH:mm:ss",        "yyyyMMdd", };

        /*
         * @param args
         */
    public static void main(String[] args) {
        String yyyyMMdd = "20110917";   
        parse(yyyyMMdd);
    }

    public static void parse(String d) {
        if (d != null) {
            for (String parse : formats) {
                SimpleDateFormat sdf = new SimpleDateFormat(parse);
                try {
                    sdf.parse(d);
                    System.out.println("Printing the value of " + parse);
                } catch (ParseException e) {

                }
            }
        }
    }
}

Вы можете сделать так, я не знаю, хороший путь или нет, но попробуйте это

сначала создайте объект SimpleDateFormat

SimpleDateFormt sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");

Теперь, когда проверьте дату, если это будет проанализировано в этом формате, то измените в соответствии с вашим форматом

try{
     Date date = sdf.parse(yourdate);
     sdf.applyPattern("yy-mm--dd or mm/dd/yyyy");
     String dateformat = sdf.format(date);
}catch(Exception ex) { // here forgot the exact exception class Parse exception was used
    // do something here
}

обновленный пост:

Возвращение формата даты из неизвестного формата строки даты в Java

Как преобразовать строку в дату, не зная формат?

Разобрать любую дату на Java

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

01.12.12 - 01 декабря 2012 года в Европе, но 12 января 2012 года в США. Это может быть и 12 декабря 2001 года.

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

Вы можете найти все наиболее регулярные выражения в формате даты и времени по следующей ссылке

http://regexlib.com/DisplayPatterns.aspx?cattabindex=4&categoryId=5&AspxAutoDetectCookieSupport=1

Если я вас правильно понимаю, вы хотите проанализировать произвольные строки (то есть строки в неизвестном формате) как даты, используя DateFormat.parse()? Тогда вам придется иметь дело с такими вопросами, как, как справиться 01-02-03 (2 января 2003 г. - 1 февраля 2003 г. и т. Д.)

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

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

package com.utility.utils.modelmapper.datetime;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class DateParser {
    private static final Map<String, String> DATE_FORMAT_REGEXPS = new HashMap<String, String>() {
        {
            put("^\\d{8}$", "yyyyMMdd");
            put("^\\d{12}$", "yyyyMMddHHmm");
            put("^\\d{8}\\s\\d{4}$", "yyyyMMdd HHmm");
            put("^\\d{14}$", "yyyyMMddHHmmss");
            put("^\\d{8}\\s\\d{6}$", "yyyyMMdd HHmmss");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}$", "dd-MM-yyyy");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}$", "yyyy-MM-dd");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}$", "MM/dd/yyyy");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}$", "yyyy/MM/dd");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}$", "dd MMM yyyy");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}$", "dd MMMM yyyy");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}$", "dd-MM-yyyy HH:mm");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy-MM-dd HH:mm");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}$", "MM/dd/yyyy HH:mm");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy/MM/dd HH:mm");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMM yyyy HH:mm");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMMM yyyy HH:mm");
            put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd-MM-yyyy HH:mm:ss");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy-MM-dd HH:mm:ss");
            put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "MM/dd/yyyy HH:mm:ss");
            put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy/MM/dd HH:mm:ss");
            put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMM yyyy HH:mm:ss");
            put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMMM yyyy HH:mm:ss");
            put("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{2}:\\d{2}\\.\\d{2}[-+]\\d{2}:\\d{2}$", "yyyy-MM-dd'T'HH:mm:ss.SSS");
        }
    };

    /**
     * To Determine the pattern by the string date value
     * 
     * @param dateString
     * @return The matching SimpleDateFormat pattern, or null if format is unknown.
     */
    public static String determineDateFormat(String dateString) {
        for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
            if (dateString.matches(regexp) || dateString.toLowerCase().matches(regexp)) {
                return DATE_FORMAT_REGEXPS.get(regexp);
            }
        }
        return null;
    }

    public static void main(String[] args) {
        parse("2011-09-27T07:04:21.97-05:00"); //here is your value
        parse("20110917");
        parse("01/02/2018");
        parse("02-01-2018 06:07:59");
        parse("02 January 2018");
    }

    public static void parse(String value) {
        if (value != null) {
            String format = determineDateFormat(value);
            if (format != null) {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                try {
                    Date date = sdf.parse(value);
                    System.out.println(String.format("Format : %s | Value : %s | Parsed Date : %s", value, date, format));
                } catch (ParseException e) {
                    // Failed the execution
                }
            }
        }
    }
}

Консольный вывод класса:

Format : 2011-09-27T07:04:21.97-05:00 | Value : Tue Sep 27 07:04:21 LINT 2011 | Parsed Date : yyyy-MM-dd'T'HH:mm:ss.SSS
Format : 20110917 | Value : Sat Sep 17 00:00:00 LINT 2011 | Parsed Date : yyyyMMdd
Format : 01/02/2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : MM/dd/yyyy
Format : 02-01-2018 06:07:59 | Value : Tue Jan 02 06:07:59 LINT 2018 | Parsed Date : dd-MM-yyyy HH:mm:ss
Format : 02 January 2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : dd MMMM yyyy

Возможно, я пропустил здесь некоторые шаблоны даты и времени, но для этого на карту должен быть добавлен правильный шаблон регулярного выражения.

Вы можете попробовать dateparser.

Он может автоматически распознавать любую строку и правильно и быстро анализировать ее на Date, Calendar, LocalDateTime, OffsetDateTime (1us~1.5us).

Он не основан ни на каких natural language analyzer или SimpleDateFormat или regex.Pattern.

С его помощью вам не нужно готовить какие-либо подходящие шаблоны, такие как yyyy-MM-dd'T'HH:mm:ss'Z' или MM/dd/yyyy HH:mm:ss так далее:

Date date = DateParserUtils.parseDate("2015-04-29T10:15:00.500+0000");
Calendar calendar = DateParserUtils.parseCalendar("2015-04-29T10:15:00.500Z");
LocalDateTime dateTime = DateParserUtils.parseDateTime("2015-04-29 10:15:00.500 +00:00");

И он имеет лучшую производительность, чем многократная попытка цикла SimpleDateFormat.

Пожалуйста, наслаждайся.

java.time и его предопределенные форматеры

Мы не можем сделать это только для любого формата даты и времени. Их тысячи, мы не можем знать их всех (завтра кто-то изобретет новый), а некоторые настолько похожи друг на друга, что мы не можем сказать, какие у нас есть.

Я предлагаю, чтобы для большинства целей вам нужно было проанализировать строку, но вам не нужно знать шаблон формата для этого. В очень многих случаях, включая пример из вашего вопроса,2011-09-27T07:04:21.97-05:00, нам не нужно указывать шаблон (ваша строка соответствует DateTimeFormatter.ISO_OFFSET_DATE_TIME).

Поскольку Java 8 вышла в 2014 году (и даже если все еще используется Java 6 или 7), используйте java.time, современный API даты и времени Java, для работы с датой и временем.

Я определяю набор средств форматирования для форматов, которые мы хотим обслуживать. Пожалуйста, замените свой собственный набор.

private static final DateTimeFormatter[] formatters = {
        DateTimeFormatter.ISO_OFFSET_DATE_TIME,
        DateTimeFormatter.RFC_1123_DATE_TIME,
        new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
                .toFormatter(),
        DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withLocale(Locale.US),
        DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm")
                .withZone(ZoneId.of("America/Los_Angeles"))
};

Следующий метод по очереди пробует форматеры, пока один из них не заработает:

private static OffsetDateTime parse(String dateTimeString) {
    for (DateTimeFormatter formatter : formatters) {
        try {
            return ZonedDateTime.parse(dateTimeString, formatter)
                    .toOffsetDateTime();
        } catch (DateTimeParseException dtpe) {
            // Ignore, try next formatter
        }
    }
    throw new IllegalArgumentException("String " + dateTimeString + " could not be parsed");
} 

Давайте попробуем это с разными строками:

    String[] dateTimeStrings = {
            "2011-09-27T07:04:21.97-05:00",
            "20110917",
            "2012-07-04",
            "12/27/2014 23:45",
            "Mon, 12 Nov 2018 01:32:10 GMT",
            "July 29, 2015 at 10:19:36 AM EDT",
    };
    
    for (String dts : dateTimeStrings) {
        try {
            System.out.format("%32s -> %s%n", dts, parse(dts));
        } catch (IllegalArgumentException iae) {
            System.out.format("%32s -> %s%n", dts, iae);
        }
    }

Выход:

    2011-09-27T07:04:21.97-05:00 -> 2011-09-27T07:04:21.970-05:00
                        20110917 -> java.lang.IllegalArgumentException: String 20110917 could not be parsed
                      2012-07-04 -> 2012-07-04T00:00Z
                12/27/2014 23:45 -> 2014-12-27T23:45-08:00
   Mon, 12 Nov 2018 01:32:10 GMT -> 2018-11-12T01:32:10Z
July 29, 2015 at 10:19:36 AM EDT -> 2015-07-29T10:19:36-04:00

Другие варианты

Методы синтаксического анализа даты и времени в нескольких форматах включают:

  • Попробуйте строку, чтобы определить ее формат, и используйте соответствующий форматер на основе этого. Он лучше всего подходит, если у вас всего несколько форматов, хотя ответ Винита Соланки показывает подробную версию для довольно многих форматов.
  • Используйте необязательные части в строке шаблона формата. Например[uuuu][uu] будет анализировать четырехзначный или двузначный год (2021 или только 21).
  • Попробуйте по очереди несколько программ форматирования, как показано в моем коде выше. Если вам действительно нужно знать шаблон, используйте массив шаблонов вместо массива средств форматирования.
  • Требование от поставщика строки также предоставить строку шаблонов формата. Однако это не всегда так просто, как может показаться.

Остерегайтесь двусмысленности. Классический пример - два форматаMM-dd-yyyy а также dd-MM-yyyy. Если мы получим строку03-09-2020, нет возможности сказать, означает ли это 9 марта или 3 сентября. Еще хуже,02-05-07 возможно yy-MM-dd, dd-MM-yy, MM-dd-yyи даже больше возможностей. Как следствие, убедитесь, что вы не включили два (или более) средства форматирования, которые могут анализировать одну и ту же строку для получения разных результатов.

Ссылки

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

HH:mm:ss.SSS => ([0-2]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(.)([0-9]{1,3})

yyyy-mm-dd => ([0-9]{4})(-)([0-1]{1,}[0-9]{1,})(-)([0-3]{1,}[0-9]{1,})
Другие вопросы по тегам