Получение неправильных данных при использовании 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.utilAPI даты и времени также был обновлен, чтобы упростить переход на 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

ONLINE DEMO

Узнайте больше о современном API Date-Time от Trail: Date Time.


Примечание . Проверьте этот ответ и этот ответ , чтобы узнать, как использовать java.timeAPI с JDBC.

Другие вопросы по тегам