Недопустимый символ шаблона 'T' при анализе строки даты на java.util.Date
У меня есть строка даты, и я хочу проанализировать ее до нормальной даты, используя API-интерфейс java Date, следующий код:
public static void main(String[] args) {
String date="2010-10-02T12:23:23Z";
String pattern="yyyy-MM-ddThh:mm:ssZ";
SimpleDateFormat sdf=new SimpleDateFormat(pattern);
try {
Date d=sdf.parse(date);
System.out.println(d.getYear());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Однако я получил исключение: java.lang.IllegalArgumentException: Illegal pattern character 'T'
Итак, мне интересно, нужно ли мне разбить строку и проанализировать ее вручную?
Кстати, я попытался добавить один символ кавычки по обе стороны от T:
String pattern="yyyy-MM-dd'T'hh:mm:ssZ";
Он также не работает.
Ответы
Ответ 1
Обновление для Java 8 и выше
Теперь вы можете просто сделать Instant.parse("2015-04-28T14:23:38.521Z")
и получить правильную вещь сейчас, тем более что вы должны использовать Instant
вместо сломанного java.util.Date
с самыми последними версиями Java.
Вы должны также использовать DateTimeFormatter
вместо SimpleDateFormatter
.
Оригинальный ответ:
Приведенное ниже объяснение остается в силе как то, что представляет формат. Но она была написана до того, как Java 8 стала повсеместной, поэтому она использует старые классы, которые вы не должны использовать, если вы используете Java 8 или выше.
Это работает со входом с трейлингом Z
, как показано:
В паттерне T
экранируется с '
с обеих сторон.
Шаблон для Z
в конце на самом деле XXX
, как описано в JavaDoc для SimpleDateFormat
просто не очень понятно на самом деле, как его использовать, так как Z
является маркером старого TimeZone
информация тоже.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class Q2597083
{
/**
* All Dates are normalized to UTC, it is up the client code to convert to the appropriate TimeZone.
*/
public static final TimeZone UTC;
/**
* @see <a href="http://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations">Combined Date and Time Representations</a>
*/
public static final String ISO_8601_24H_FULL_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
/**
* 0001-01-01T00:00:00.000Z
*/
public static final Date BEGINNING_OF_TIME;
/**
* 292278994-08-17T07:12:55.807Z
*/
public static final Date END_OF_TIME;
static
{
UTC = TimeZone.getTimeZone("UTC");
TimeZone.setDefault(UTC);
final Calendar c = new GregorianCalendar(UTC);
c.set(1, 0, 1, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
BEGINNING_OF_TIME = c.getTime();
c.setTime(new Date(Long.MAX_VALUE));
END_OF_TIME = c.getTime();
}
public static void main(String[] args) throws Exception
{
final SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_24H_FULL_FORMAT);
sdf.setTimeZone(UTC);
System.out.println("sdf.format(BEGINNING_OF_TIME) = " + sdf.format(BEGINNING_OF_TIME));
System.out.println("sdf.format(END_OF_TIME) = " + sdf.format(END_OF_TIME));
System.out.println("sdf.format(new Date()) = " + sdf.format(new Date()));
System.out.println("sdf.parse(\"2015-04-28T14:23:38.521Z\") = " + sdf.parse("2015-04-28T14:23:38.521Z"));
System.out.println("sdf.parse(\"0001-01-01T00:00:00.000Z\") = " + sdf.parse("0001-01-01T00:00:00.000Z"));
System.out.println("sdf.parse(\"292278994-08-17T07:12:55.807Z\") = " + sdf.parse("292278994-08-17T07:12:55.807Z"));
}
}
Создает следующий вывод:
sdf.format(BEGINNING_OF_TIME) = 0001-01-01T00:00:00.000Z
sdf.format(END_OF_TIME) = 292278994-08-17T07:12:55.807Z
sdf.format(new Date()) = 2015-04-28T14:38:25.956Z
sdf.parse("2015-04-28T14:23:38.521Z") = Tue Apr 28 14:23:38 UTC 2015
sdf.parse("0001-01-01T00:00:00.000Z") = Sat Jan 01 00:00:00 UTC 1
sdf.parse("292278994-08-17T07:12:55.807Z") = Sun Aug 17 07:12:55 UTC 292278994
Ответ 2
ТЛ; др
Instant.parse( "2010-10-02T12:23:23Z" )
ISO 8601
Этот формат определяется стандартом ISO 8601 для строковых форматов даты и времени.
Оба:
… Использовать форматы ISO 8601 по умолчанию для анализа и генерации строк.
Как правило, вам следует избегать использования старого java.util.Date/.Calendar & java.text.SimpleDateFormat классы, так как они общеизвестно хлопотны, сбивают с толку и имеют недостатки. Если требуется для взаимодействия, вы можете конвертировать туда и обратно.
java.time
В Java 8 и более поздние версии встроен новый java.time. Вдохновлено Joda-Time, определено JSR 310 и расширено проектом ThreeTen-Extra.
Instant instant = Instant.parse( "2010-10-02T12:23:23Z" ); // 'Instant' is always in UTC.
Преобразовать в старый класс.
java.util.Date date = java.util.Date.from( instant ); // Pass an 'Instant' to the 'from' method.
часовой пояс
При необходимости вы можете назначить часовой пояс.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Define a time zone rather than rely implicitly on JVMs current default time zone.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); // Assign a time zone adjustment from UTC.
Преобразовать.
java.util.Date date = java.util.Date.from( zdt.toInstant() ); // Extract an 'Instant' from the 'ZonedDateTime' to pass to the 'from' method.
Joda времени
ОБНОВЛЕНИЕ: проект Joda-Time сейчас находится в режиме обслуживания. Команда советует перейти на классы java.time.
Вот пример кода в Joda-Time 2.8.
org.joda.time.DateTime dateTime_Utc = new DateTime( "2010-10-02T12:23:23Z" , DateTimeZone.UTC ); // Specifying a time zone to apply, rather than implicitly assigning the JVMs current default.
Преобразовать в старый класс. Обратите внимание, что назначенный часовой пояс теряется при конвертации, поскольку j.u.Date нельзя назначить часовой пояс.
java.util.Date date = dateTime_Utc.toDate(); // The 'toDate' method converts to old class.
часовой пояс
При необходимости вы можете назначить часовой пояс.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime_Montreal = dateTime_Utc.withZone ( zone );
![Table of date-time types in Java, both modern and legacy.]()
О java.time
Среда java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Проект Joda-Time, который теперь находится в режиме обслуживания, рекомендует выполнить переход на классы java.time.
Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите в Кару множество примеров и объяснений. Спецификация: JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в классах java.sql.*
.
Где взять классы java.time?
![Table of which java.time library to use with which version of Java or Android.]()
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и еще.