Как получить заданный формат строки даты (шаблон) в 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
Я думаю, что вы должны попытаться проанализировать входную строку с некоторыми предопределенными шаблонами. Тот, который работает, тот, который вам нужен. Помните, что некоторые шаблоны довольно сложны.
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
и даже больше возможностей. Как следствие, убедитесь, что вы не включили два (или более) средства форматирования, которые могут анализировать одну и ту же строку для получения разных результатов.
Ссылки
- Учебник Oracle: Date Time, объясняющий, как использовать java.time.
- Прекрасный ответ Арвинда Кумара Авинаша, показывающий использование дополнительных частей в строке шаблона формата для анализа различных форматов.
Вам нужно будет взять начальную строку даты и преобразовать ее в объект даты, а затем передать этот преобразованный объект даты и отформатировать его в требуемую строку.
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,})