Datetime или timestamp
На днях я столкнулся с тем, что многие разработчики не знают в чём отличие типов данных DATETIME и TIMESTAMP в MySQLе, а так же как хранить дату и время, если необходимо учитывать разные часовые пояса для разных пользователей веб-приложения. Поэтому хочу дать ниже разъяснения с пояснениями.
DATETIME
Хранит время в виде целого числа вида YYYYMMDDHHMMSS, используя для этого 8 байтов. Это время не зависит от временной зоны. Оно всегда отображается при выборке точно так же, как было сохранено, независимо от того какой часовой пояс установлен в MySQL. Даю пример:
mysql> create table `dt1` ( col datetime NOT NULL );
mysql> SET @@session.time_zone=’+00:00′;
mysql> select now();
+———————+
| now() |
+———————+
| 2009-06-04 18:13:56 |
+———————+
mysql> insert into dt1 values(now());
mysql> insert into dt1 values(now());
TIMESTAMP
Хранит 4-байтное целое число, равное количеству секунд, прошедших с полуночи 1 января 1970 года по усреднённому времени Гринвича (т.е. нулевой часовой пояс, точка отсчёта часовых поясов). При получении из базы отображается с учётом часового пояса. Часовой пояс может быть задан в операционной системе, глобальных настройках MySQL или в конкретной сессии. Запомните, что сохраняется всегда количество секунд по UTC (универсальное координированное время, солнечное время на меридиане Гринвича), а не по локальному часовому поясу. Пример:
Ещё одно отличие! TIMESTAMP по умолчанию NOT NULL, а его значение по умолчанию равно NOW().
mysql> insert into dt1 values(null);
ERROR 1048 (23000): Column ‘col’ cannot be null
mysql> insert into tm1 values(null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tm1;
+———————+
| col |
+———————+
| 2009-06-04 18:25:08 |
| 2009-06-04 18:25:26 |
| 2009-06-04 18:32:50 |
+———————+
Дополнение. Для тех, кого смущает использование функции NOW().
CURRENT_TIMESTAMP (Transact-SQL)
Эта функция возвращает текущую системную метку времени базы данных в виде значения datetime без смещения часового пояса базы данных. CURRENT_TIMESTAMP наследует это значение от операционной системы компьютера, на котором работает экземпляр SQL Server.
Эта функция ANSI SQL эквивалентна функции GETDATE.
Обзор всех типов данных и функций даты и времени в языке Transact-SQL см. в статье Типы данных и функции даты и времени.

Синтаксис
Ссылки на описание синтаксиса Transact-SQL для SQL Server 2014 и более ранних версий, см. в статье Документация по предыдущим версиям.
Аргументы
Эта функция не имеет аргументов.
Тип возвращаемых данных
datetime
Remarks
Функция CURRENT_TIMESTAMP может использоваться в инструкциях Transact-SQL везде, где допустимо использование выражения datetime.
CURRENT_TIMESTAMP является недетерминированной функцией. Невозможно проиндексировать представления и выражения, ссылающиеся на этот столбец.
Примеры
В приведенных ниже примерах с помощью шести системных функций SQL Server, которые возвращают текущую дату и время, возвращается дата, время или дата и время. Значения возвращаются последовательно, поэтому могут различаться на доли секунды. Обратите внимание на то, что возвращаемые значения будут соответствовать фактическим дню и времени выполнения.
Как работать с метками времени (timestamp) в PostgreSQL?
Тема работы с временными метками в PostgreSQL плохо раскрыта в русскоязычных профильных публикациях в Интернете и служит частым источником проблем в работе программистов. Предлагаю вашему вниманию перевод материала от Hubert Lubaczewski, автора популярного зарубежного блога depesz.com. Надеюсь, статья будет для вас полезна!
Время от времени в IRC или в почтовых рассылках кто-нибудь задает вопросы, которые показывают глубокое непонимание (или недостаток понимания) меток времени, особенно тех, которые учитывают часовые пояса. Так как я уже сталкивался с этим ранее, позвольте мне рассказать, что такое timestamps, как с ними работать и с какими наиболее распространенными загвоздками вы можете столкнуться.
У нас есть два типа данных, которые мы можем использовать:
Давайте представим, что у вас есть временная метка “2014-04-04 20:00:00″. О чем она вам говорит? К сожалению, не о многом. Всё зависит от того, о какой точке планеты идет речь. Восемь вечера 4-го апреля – это разный момент времени в Лос Анджелесе, Чикаго, Лондоне, Варшаве или Москве. В этом проблема часовых поясов.
Конечно, вы можете подумать: «Я всегда буду в одном часовом поясе, мне не нужно заморочек с поддержкой разных временных зон. В моем часовом поясе даты и времени будет вполне достаточно, чтобы отметить какой-либо момент времени, ведь именно так мы делаем в «реальной жизни».
Но так ли это на самом деле?
Представим, что у вас есть метка ‘2013-10-27 02:00:00′, и вы знаете, что ваше приложение привязано к польскому времени. В этом случае, вам уже не повезло, потому что это может быть 2 часа ночи по центрально-европейскому летнему времени (CEST) или на час больше, по обычному центрально-европейскому времени. Всё из-за сезонного перевода часов.
Я считаю, что использование временных меток без часового пояса почти всегда является багом, и его нужно исправлять. Проблем становится еще больше, если, записи в вашем приложении поступают из разных часовых поясов (например, приложение-планировщик).
Так что самое очевидное решение – использовать метки времени с часовыми поясами (timestamptz).
Во-первых, это не займет больше места на диске:
Как же это работает? Метка должна знать часовой пояс, так почему же для этого не требуется больше места?
Дело в том, что она не знает часовой пояс. Внутри, все значения в колонках timestamptz указаны в формате UTC (всемирное координированное время).
У UTC есть приятные особенности: у него нет смещения (он сам является отправной точкой, от которой считаются смещения других часовых поясов), и у него нет разницы между летним и зимним временем. Так что любая временная метка в формате UTC всегда гарантированно указывает только на одну точку во времени.
Но если всё время указывать по UTC, то как я узнаю время в нужном мне часовом поясе?
Каждый раз, когда речь идет о значениях timestamptz, если часовой пояс не указан, то PostgreSQL использует заранее сконфигурированное время. И вы можете конфигурировать его разными способами:
Следующие два способа меняют значение по-умолчанию для выбранной базы данных и пользователя.
Последний способ можно использовать, если вы хотите, чтобы ваше соединение с базой данных работало с иными настройками.
Примите во внимание, как при этом меняется вывод now():
Так что каждый раз, когда вы просматриваете или меняете значения timestamptz, PostgreSQL конвертирует их в/из UTC.
Это значит, что значения можно легко сравнивать (все они в одном часовом поясе, нет сдвигов на летнее или зимнее время, так что сравнение всегда возможно).
Что произошло? Почему не показывается 8 вечера?
Причина проста – в запрос я вставил timestamp в каком-то часовом поясе. Внутри, метка была сконвертирована в UTC, а затем, снова сконвертирована (возможно, даже без UTC, я не уверен) в мой обычный часовой пояс, которым является:
Если бы у меня был установлен часовой пояс Лос Анджелеса, то результат запроса был бы таким:
Важно понимать, что выводимое значение всегда принимает во внимание настройку часового пояса.
Есть еще один способ получить 20:00 в Лос Анджелесе:
Очень важно добавлять “::timestamp» после значения, иначе мы получим что-то странное:
Что здесь произошло? Откуда взялось 11:00?
Значение в кавычках (2014-04-04 20:00:00) воспринимается как timestamptz, что значит 8 вечера в моём часовом поясе:
И только после перевода значения в мой часовой пояс PG считывает “at time zone …», которая используется для отображения времени в выбранном часовом поясе.
Таким образом, timestamp at time zone выдаёт значение timestamptz, которое показывает момент, когда местное время в выбранном часовом поясе было таким, как указано в команде.
А timestamptz at time zone выдаёт значение timestamp, которое показывает, каким было время в выбранном часовом поясе в указанный момент времени.
Это звучит немного путанно, поэтому давайте я приведу примеры:
Интересно то, что мы можем использовать это для перевода времени из одного часового пояса в другой, даже если Pg не находится ни в одном из них.
Допустим, мы хотим узнать, который час в Лос Анджелесе, когда в Москве — 8 утра. Моё местное время следующее:
Пользы от него мало.
Для начала нам нужно определить точку во времени (в формате timestamptz), которая показывает 8 утра в Москве:
Это говорит мне о том, что она соответствует 6 утра в моём часовом поясе. Но мы хотим узнать время в Лос Анджелесе. Я мог бы написать ‘2014-04-04 06:00:00+02′ в часовом поясе ‘LA’, но можно сделать по-другому:
Надеюсь, теперь вам всё ясно. Я сам довольно долго пытался разобраться в этом вопросе, и наконец-то всё понял 🙂
У всего этого есть один интересный побочный эффект: не так-то просто добавить индексы к функциям, работающим с timestamptz. Например, вы не можете создать индекс, который будет использоваться для получения дня недели:
Как показано в примере выше, причина очень проста – одна и та же точка во времени может относиться к разным дням недели в зависимости от часового пояса. А поскольку to_char() использует текущий часовой пояс, он может выдавать разные значения для одних и тех же исходных данных в зависимости от настроек часового пояса в системе:
Одна и та же точка во времени, но разные дни. Это могут быть разные месяцы или даже разные года, в зависимости от того, где это было.
Временная метка (без часового пояса) здесь “проявляет” сильную сторону – так как в ней не указан часовой пояс, её можно спокойно использовать для извлечения информации.
Но мы же знаем, как переводить timestamptz в timestamp. Нужно просто указать ей часовой пояс. Поэтому мы можем попробовать сделать так:
Но, к сожалению, ничего не выходит. Дело в том, что to_char слишком разносторонний. Вы можете использовать to_char вот так:
На этот раз мы получаем другие результаты не из-за часового пояса, а из-за локали.
Правильным решением проблемы индексирования будет написать свою собственную функцию, которая будет вызывать to_char в абсолютно постоянной «среде», а затем ее уже индексировать. Вот так:
А теперь мы можем использовать ее для индексирования:
Это безопасно, потому что сама функция заставляет часовой пояс принимать значение «Poland», и она вызывает to_char таким образом, чтобы игнорировать значение локали (другими словами, в формате to_char нет префикса TM).
Естественно, чтобы воспользоваться этим индексом, все запросы должны также использовать эту функцию:
Еще одна важная вещь при работе с часовыми поясами – получение времени Unix, или так называемой эпохи. В целом, это просто:
Интересно то, что оно не зависит от часового пояса:
Причина, известная не всем, кроется в том, что время Unix всегда принимается в часовом поясе UTC. Это значит, что, когда вы извлекаете эпоху из временной метки timestamp, PG предполагает, что она находится в UTC. Из чего вытекают следующие потенциальные проблемы:
В первом случае Pg получает «точку во времени», которая внутренне конвертируется в UTC (а когда отображается – преобразовывается в мой часовой пояс, +2).
Во втором случае временная метка находится в моём часовом поясе, но предполагается, что это UTC (без конвертации!), и эпоха берется от значения ‘2014-04-04 21:19:01.456205 UTC’, а не ‘2014-04-04 21:19:01.456205+02′.
Короче говоря, старайтесь избегать timestamp и используйте timestamptz.
Последнее, о чём я хотел бы сказать – это не баг или потенциальная проблема, а скорее функциональность, о которой многие не знают.
Как вы видели, PostgreSQL использует timestamp (и timestamptz) с точностью до микросекунд. Многие люди настаивают на том, чтобы точность была только до секунды, хотя лично мне это не нравится.
И timestamp, и timestamptz (и другие виды данных, относящиеся ко времени) могут иметь дополнительную точность (“precision”).
Давайте я приведу простой пример:
Конечно, вы можете использовать это и в таблицах:
Отлично! Вам не нужно менять “now()» или что-либо еще, просто добавьте точность к типу данных, и она всё скорректирует.
Я упомянул, что мне это не нравится. Причина проста – в любой достаточно нагруженной системе секунда – слишком низкий уровень точности. Тем более, что хранение данных с точностью до микросекунды ничего мне не стоит, но может быть полезным. С другой стороны, если данные до микросекунд, то как мне сделать, чтобы значения отображались без долей секунды?
Все просто: я использую (в запросах SELECT) фунуции to_char(), или date_trunc, или даже приведение к типу timestamptz(0):
Более подробно о том, как работать с timestamps, мы собираемся рассказать на конференции PG Day’16 Russia в июле 2016 года! Готовьте свои вопросы, мы постараемся на них ответить.
Типы данных и функции даты и времени (Transact-SQL)
В разделах этой статьи представлен обзор всех типов данных и функций даты и времени Transact-SQL.
Типы данных даты и времени
Типы данных даты и времени Transact-SQL перечислены в следующей таблице:
| Тип данных | Формат | Диапазон | Точность | Объем памяти (в байтах) | Определяемая пользователем точность в долях секунды | Смещение часового пояса |
|---|---|---|---|---|---|---|
| time | чч:мм:сс[.ннннннн] | От 00:00:00.0000000 до 23:59:59.9999999 | 100 наносекунд | от 3 до 5 | Да | Нет |
| date | ГГГГ-ММ-ДД | От 0001-01-01 до 31.12.99 | 1 день | 3 | Нет | Нет |
| smalldatetime | ГГГГ-ММ-ДД чч:мм:сс | От 01.01.1900 до 06.06.2079 | 1 минута | 4 | нет | Нет |
| datetime | ГГГГ-ММ-ДД чч:мм:сс[.ннн] | От 01.01.1753 до 31.12.9999 | 0,00333 секунды | 8 | Нет | Нет |
| datetime2 | ГГГГ-ММ-ДД чч:мм:сс[.ннннннн] | От 0001-01-01 00:00:00.0000000 до 9999-12-31 23:59:59.9999999 | 100 наносекунд | От 6 до 8 | Да | Нет |
| datetimeoffset | ГГГГ-ММ-ДД чч:мм:сс[.ннннннн] [+|-]чч:мм | От 0001-01-01 00:00:00.0000000 до 9999-12-31 23:59:59.9999999 (время в формате UTC) | 100 наносекунд | От 8 до 10 | Да | Да |
Тип данных Transact-SQL rowversion не относится к типам данных даты и времени. Тип данных timestamp является устаревшим синонимом rowversion.
Функции даты и времени
В следующих таблицах приводятся функции даты и времени Transact-SQL. Дополнительные сведения о детерминизме см. в статье Детерминированные и недетерминированные функции.
Функции, возвращающие значения системной даты и времени
Transact-SQL наследует все значения системной даты и времени от операционной системы компьютера, на котором работает экземпляр SQL Server.
Высокоточные функции системной даты и времени
SQL Server 2019 (15.x) получает значения даты и времени с помощью функции GetSystemTimeAsFileTime() Windows API. Точность зависит от физического оборудования и версии Windows, в которой запущен экземпляр SQL Server. Точность возвращаемых значений этого API-интерфейса задана равной 100 нс. Точность может быть определена с помощью метода GetSystemTimeAdjustment() API-интерфейса Windows.
Что такое timestamp sql
Таблица 8.9. Типы даты/времени
| Имя | Размер | Описание | Наименьшее значение | Наибольшее значение | Точность |
|---|---|---|---|---|---|
| timestamp [ ( p ) ] [ without time zone ] | 8 байт | дата и время (без часового пояса) | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
| timestamp [ ( p ) ] with time zone | 8 байт | дата и время (с часовым поясом) | 4713 до н. э. | 294276 н. э. | 1 микросекунда |
| date | 4 байта | дата (без времени суток) | 4713 до н. э. | 5874897 н. э. | 1 день |
| time [ ( p ) ] [ without time zone ] | 8 байт | время суток (без даты) | 00:00:00 | 24:00:00 | 1 микросекунда |
| time [ ( p ) ] with time zone | 12 байт | время дня (без даты), с часовым поясом | 00:00:00+1559 | 24:00:00-1559 | 1 микросекунда |
| interval [ поля ] [ ( p ) ] | 16 байт | временной интервал | -178000000 лет | 178000000 лет | 1 микросекунда |
Примечание
Тип interval дополнительно позволяет ограничить набор сохраняемых полей следующими фразами:
Типы abstime и reltime имеют меньшую точность и предназначены для внутреннего использования. Эти типы не рекомендуется использовать в обычных приложениях; их может не быть в будущих версиях.
8.5.1. Ввод даты/времени
Помните, что любые вводимые значения даты и времени нужно заключать в апострофы, как текстовые строки. За дополнительной информацией обратитесь к Подразделу 4.1.2.7. SQL предусматривает следующий синтаксис:
8.5.1.1. Даты
Таблица 8.10. Вводимые даты
| Пример | Описание |
|---|---|
| 1999-01-08 | ISO 8601; 8 января в любом режиме (рекомендуемый формат) |
| January 8, 1999 | воспринимается однозначно в любом режиме datestyle |
| 1/8/1999 | 8 января в режиме MDY и 1 августа в режиме DMY |
| 1/18/1999 | 18 января в режиме MDY ; недопустимая дата в других режимах |
| 01/02/03 | 2 января 2003 г. в режиме MDY ; 1 февраля 2003 г. в режиме DMY и 3 февраля 2001 г. в режиме YMD |
| 1999-Jan-08 | 8 января в любом режиме |
| Jan-08-1999 | 8 января в любом режиме |
| 08-Jan-1999 | 8 января в любом режиме |
| 99-Jan-08 | 8 января в режиме YMD ; ошибка в других режимах |
| 08-Jan-99 | 8 января; ошибка в режиме YMD |
| Jan-08-99 | 8 января; ошибка в режиме YMD |
| 19990108 | ISO 8601; 8 января 1999 в любом режиме |
| 990108 | ISO 8601; 8 января 1999 в любом режиме |
| 1999.008 | год и день года |
| J2451187 | Юлианский день |
| January 8, 99 BC | 99 до н. э. |
8.5.1.2. Время
Таблица 8.11. Вводимое время
| Пример | Описание | |
|---|---|---|
| 04:05:06.789 | ISO 8601 | |
| 04:05:06 | ISO 8601 | |
| 04:05 | ISO 8601 | |
| 040506 | ISO 8601 | |
| 04:05 AM | то же, что и 04:05; AM не меняет значение времени | |
| 04:05 PM | то же, что и 16:05; часы должны быть 04:05:06.789-8 | ISO 8601, с часовым поясом в виде смещения от UTC |
| 04:05:06-08:00 | ISO 8601, с часовым поясом в виде смещения от UTC | |
| 04:05-08:00 | ISO 8601, с часовым поясом в виде смещения от UTC | |
| 040506-08 | ISO 8601, с часовым поясом в виде смещения от UTC | |
| 040506+0730 | ISO 8601, с часовым поясом, задаваемым нецелочисленным смещением от UTC | |
| 040506+07:30:00 | Смещение от UTC, заданное до секунд (не допускается в ISO 8601) | |
| 04:05:06 PST | часовой пояс задаётся аббревиатурой | |
| 2003-04-12 04:05:06 America/New_York | часовой пояс задаётся полным названием |
Таблица 8.12. Вводимый часовой пояс
| Пример | Описание |
|---|---|
| PST | аббревиатура (Pacific Standard Time, Стандартное тихоокеанское время) |
| America/New_York | полное название часового пояса |
| PST8PDT | указание часового пояса в стиле POSIX |
| -8:00:00 | смещение часового пояса PST от UTC |
| -8:00 | смещение часового пояса PST от UTC (расширенный формат ISO 8601) |
| -800 | смещение часового пояса PST от UTC (стандартный формат ISO 8601) |
| -8 | смещение часового пояса PST от UTC (стандартный формат ISO 8601) |
| zulu | принятое у военных сокращение UTC |
| z | Краткая форма zulu (также определена в ISO 8601) |
Подробнее узнать о том, как указывается часовой пояс, можно в Подразделе 8.5.3.
8.5.1.3. Даты и время
В константе типа timestamp without time zone Postgres Pro просто игнорирует часовой пояс. То есть результирующее значение вычисляется только из полей даты/времени и не подстраивается под указанный часовой пояс.
8.5.1.4. Специальные значения
Таблица 8.13. Специальные значения даты/времени
Внимание
8.5.2. Вывод даты/времени
Таблица 8.14. Стили вывода даты/время
| Стиль | Описание | Пример |
|---|---|---|
| ISO | ISO 8601, стандарт SQL | 1997-12-17 07:37:16-08 |
| SQL | традиционный стиль | 12/17/1997 07:37:16.00 PST |
| Postgres | изначальный стиль | Wed Dec 17 07:37:16 1997 PST |
| German | региональный стиль | 17.12.1997 07:37:16.00 PST |
Примечание
ISO 8601 указывает, что дата должна отделяться от времени буквой T в верхнем регистре. Postgres Pro принимает этот формат при вводе, но при выводе вставляет вместо T пробел, как показано выше. Это сделано для улучшения читаемости и для совместимости с RFC 3339 и другими СУБД.
Таблица 8.15. Соглашения о порядке компонентов даты
| Параметр datestyle | Порядок при вводе | Пример вывода |
|---|---|---|
| SQL, DMY | день / месяц / год | 17/12/1997 15:37:16.00 CET |
| SQL, MDY | месяц / день / год | 12/17/1997 07:37:16.00 PST |
| Postgres, DMY | день / месяц / год | Wed 17 Dec 07:37:16 1997 PST |
Для большей гибкости при форматировании выводимой даты/времени можно использовать функцию to_char (см. Раздел 9.8).
8.5.3. Часовые пояса
Часовые пояса и правила их применения определяются, как вы знаете, не только по географическим, но и по политическим соображениям. Часовые пояса во всём мире были более-менее стандартизированы в начале прошлого века, но они продолжают претерпевать изменения, в частности это касается перехода на летнее время. Для расчёта времени в прошлом Postgres Pro получает исторические сведения о правилах часовых поясов из распространённой базы данных IANA (Olson). Для будущего времени предполагается, что в заданном часовом поясе будут продолжать действовать последние принятые правила.
Поэтому мы советуем использовать часовой пояс с типами, включающими и время, и дату. Мы не рекомендуем использовать тип time with time zone (хотя Postgres Pro поддерживает его для старых приложений и совместимости со стандартом SQL ). Для типов, включающих только дату или только время, в Postgres Pro предполагается местный часовой пояс.
Postgres Pro позволяет задать часовой пояс тремя способами:
Помимо аббревиатур и названий часовых поясов Postgres Pro принимает указания часовых поясов в стиле POSIX, как описано в Разделе B.5. Этот вариант обычно менее предпочтителен, чем использование именованного часового пояса, но он может быть единственным возможным, если для нужного часового пояса нет записи в базе данных IANA.
Вкратце, различие между аббревиатурами и полными названиями заключаются в следующем: аббревиатуры представляют определённый сдвиг от UTC, а полное название подразумевает ещё и местное правило по переходу на летнее время, то есть, возможно, два сдвига от UTC. Например, 2014-06-04 12:00 America/New_York представляет полдень по местному времени в Нью-Йорк, что для данного дня было бы летним восточным временем (EDT или UTC-4). Так что 2014-06-04 12:00 EDT обозначает тот же момент времени. Но 2014-06-04 12:00 EST задаёт стандартное восточное время (UTC-5), не зависящее о того, действовало ли летнее время в этот день.
Независимо от формы, регистр в названиях и аббревиатурах часовых поясов не важен. (В PostgreSQL до версии 8.2 он где-то имел значение, а где-то нет.)
Параметр конфигурации TimeZone можно установить в postgresql.conf или любым другим стандартным способом, описанным в Главе 18. Часовой пояс может быть также определён следующими специальными способами:
8.5.4. Ввод интервалов
Значения типа interval могут быть записаны в следующей расширенной форме:
Таблица 8.16. Коды единиц временных интервалов ISO 8601
| Код | Значение |
|---|---|
| Y | годы |
| M | месяцы (в дате) |
| W | недели |
| D | дни |
| H | часы |
| M | минуты (во времени) |
| S | секунды |
В альтернативном формате:
Таблица 8.17. Ввод интервалов
| Пример | Описание |
|---|---|
| 1-2 | Стандартный формат SQL: 1 год и 2 месяца |
| 3 4:05:06 | Стандартный формат SQL: 3 дня 4 часа 5 минут 6 секунд |
| 1 year 2 months 3 days 4 hours 5 minutes 6 seconds | Традиционный формат Postgres: 1 год 2 месяца 3 дня 4 часа 5 минут 6 секунд |
| P1Y2M3DT4H5M6S | « Формат с кодами » ISO 8601: то же значение, что и выше |
| P0001-02-03T04:05:06 | « Альтернативный формат » ISO 8601: то же значение, что и выше |
8.5.5. Вывод интервалов
Стиль sql_standard выдаёт результат, соответствующий стандарту SQL, если значение интервала удовлетворяет ограничениям стандарта (и содержит либо только год и месяц, либо только день и время, и при этом все его компоненты одного знака). В противном случае выводится год-месяц, за которым идёт дата-время, а в компоненты для однозначности явно добавляются знаки.
Вывод в стиле iso_8601 соответствует « формату с кодами » описанному в разделе 4.4.3.2 формата ISO 8601.
Таблица 8.18. Примеры стилей вывода интервалов



