Получение неправильных данных при использовании SimpleDateFormat.parse()
Я получаю странную ошибку, когда пытаюсь разобрать строку как календарь. Кажется, что он портит объект Date, который я использую, чтобы установить время календаря результата. Ошибка довольно противоречива (или я не вижу в этом логики). Кто-нибудь может указать, что я могу делать неправильно?
public class caltest{
public static final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS");
public static void main(String[] args) {
String date1 = "1992-03-11 12:00:12.123";
String date2 = "1993-03-11 12:00:12.123";
String date3 = "1994-03-11 12:00:12.123";
String date4 = "1995-03-11 12:00:12.123";
parseStringAsCalendar(date1);
parseStringAsCalendar(date2);
parseStringAsCalendar(date3);
parseStringAsCalendar(date4);
}
public static String calendarToString(Calendar cal) {
return sdf.format(cal.getTime());
}
public static Calendar parseStringAsCalendar(String s) {
Date time = null;
try {
time = sdf.parse(s);
} catch (ParseException e) {
System.out.println("Exception");
e.printStackTrace();
}
System.out.println(time.toString());
GregorianCalendar ret = new GregorianCalendar();
ret.setTime(time);
return ret;
}
}
Выход:
Sun Dec 29 12:00:12 CET 1991
Sun Dec 27 12:00:12 CET 1992
Sun Dec 26 12:00:12 CET 1993
Sun Jan 01 12:00:12 CET 1995
3 ответа
Вы используете YYYY
в вашем спецификаторе формата, который является недельным годом (на Java 7, я полагаю). Ты хочешь yyyy
, который просто "год". (См. SimpleDateFormat
документация.)
Я подозреваю, что остальная часть даты вышла из-за того, что вы также пытались указать месяц и день, которые на самом деле не являются "особенностями" в году недели... если вы указали "год недели недели" и день неделю, это могло бы дать более ощутимые результаты, но только если вы действительно хотели использовать недельные годы, в чем я сомневаюсь:)
Использовать этот:
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Это нижний регистр y
в течение года, не в верхнем регистре Y
, С этим, результат:
Wed Mar 11 12:00:12 EST 1992
Thu Mar 11 12:00:12 EST 1993
Fri Mar 11 12:00:12 EST 1994
Sat Mar 11 12:00:12 EST 1995
Посмотреть здесь:
Java.время
Вопрос и существующие ответы используют то, что было правильным сделать в 2012 году. В марте 2014 года API даты и времени и их API форматирования,SimpleDateFormat
были вытеснены современным API Date-Time . С тех пор настоятельно рекомендуется прекратить использование устаревшего API даты и времени.
Решение с использованием современного API даты и времени: Как вы можете узнать из документации , символY
используется для недельного года, тогда как в этом случае нам нужно ( year-of-era ). Однако я предпочитаю
u
к
y
.
Обратите внимание, что ваша строка даты и времени имеет только единицы даты и времени (без часового пояса или смещения часового пояса и т. д.). API предоставляет вамLocalDateTime
для представления такого объекта.
В случае, если вам нужно получить объект даты и времени с часовым поясом или тот, который представляет только момент времени, предоставляет вам определенные типы. Вы можете проверить обзор типов здесь .
С Java 8,java.util
API даты и времени также был обновлен, чтобы упростить переход на API, например, если вам нужноjava.util.Date
экземпляр изInstant
, вы можете использовать Date#from
.
Демо:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Date;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String strDateTime = "1992-03-11 12:00:12.123";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
// An alternative parser
DateTimeFormatter ldtParser = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ').append(DateTimeFormatter.ISO_LOCAL_TIME).toFormatter(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, parser);
System.out.println(ldt);
// Parsing using the alternative parser
ldt = LocalDateTime.parse(strDateTime, ldtParser);
System.out.println(ldt);
// Converting LocalDateTime to a ZonedDateTime
// Replace ZoneId.systemDefault() with applicable ZoneId e.g.
// ZoneId.of("America/New_York")
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ldt.atZone(zoneId);
System.out.println(zdt);
// Alternatively,
zdt = ZonedDateTime.of(ldt, zoneId);
System.out.println(zdt);
// Obtaining an Instant
Instant instant = zdt.toInstant();
System.out.println(instant);
// In case you need an instance of java.util.Date
Date date = Date.from(instant);
}
}
Вывод в моем часовом поясе, Европа/Лондон:
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z
Узнайте больше о современном API Date-Time от Trail: Date Time.
Примечание . Проверьте этот ответ и этот ответ , чтобы узнать, как использовать
java.time
API с JDBC.