DateTime
В модуле DateTime основным внутренним форматом представления является Resource<TM>
, хранящий следующие компоненты даты:
- Year (12 бит);
- Month (4 бита);
- Day (5 бит);
- Hour (5 бит);
- Minute (6 бит);
- Second (6 бит);
- Microsecond (20 бит);
- TimezoneId (16 бит);
- DayOfYear (9 бит) — день от начала года;
- WeekOfYear (6 бит) — неделя от начала года, 1 января всегда относится к первой неделе;
- WeekOfYearIso8601 (6 бит) — неделя года согласно ISO 8601 (первой неделей считается та, в которой 4 января);
- DayOfWeek (3 бита) — день недели.
Если таймзона не GMT, то в компонентах хранится локальное время в соответствующей таймзоне.
Split
Преобразование из простого типа во внутреннее представление. Всегда успешно при непустом входе.
Список функций
DateTime::Split(Date{Flags:AutoMap}) -> Resource<TM>
DateTime::Split(Datetime{Flags:AutoMap}) -> Resource<TM>
DateTime::Split(Timestamp{Flags:AutoMap}) -> Resource<TM>
DateTime::Split(TzDate{Flags:AutoMap}) -> Resource<TM>
DateTime::Split(TzDatetime{Flags:AutoMap}) -> Resource<TM>
DateTime::Split(TzTimestamp{Flags:AutoMap}) -> Resource<TM>
Функции, принимающие на вход Resource<TM>
, могут быть вызваны непосредственно от простого типа даты/времени. В этом случае будет сделано неявное преобразование через вызов соответствующей функции Split
.
Make...
Сборка простого типа из внутреннего представления. Всегда успешна при непустом входе.
Список функций
DateTime::MakeDate(Resource<TM>{Flags:AutoMap}) -> Date
DateTime::MakeDatetime(Resource<TM>{Flags:AutoMap}) -> Datetime
DateTime::MakeTimestamp(Resource<TM>{Flags:AutoMap}) -> Timestamp
DateTime::MakeTzDate(Resource<TM>{Flags:AutoMap}) -> TzDate
DateTime::MakeTzDatetime(Resource<TM>{Flags:AutoMap}) -> TzDatetime
DateTime::MakeTzTimestamp(Resource<TM>{Flags:AutoMap}) -> TzTimestamp
Примеры
SELECT
DateTime::MakeTimestamp(DateTime::Split(Datetime("2019-01-01T15:30:00Z"))),
-- 2019-01-01T15:30:00.000000Z
DateTime::MakeDate(Datetime("2019-01-01T15:30:00Z")),
-- 2019-01-01
DateTime::MakeTimestamp(DateTime::Split(TzDatetime("2019-01-01T00:00:00,Europe/Moscow"))),
-- 2018-12-31T21:00:00Z (конвертация в UTC)
DateTime::MakeDate(TzDatetime("2019-01-01T12:00:00,GMT"))
-- 2019-01-01 (Datetime -> Date с неявным Split)
Get...
Взятие компоненты внутреннего представления.
Список функций
DateTime::GetYear(Resource<TM>{Flags:AutoMap}) -> Uint16
DateTime::GetDayOfYear(Resource<TM>{Flags:AutoMap}) -> Uint16
DateTime::GetMonth(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetMonthName(Resource<TM>{Flags:AutoMap}) -> String
DateTime::GetWeekOfYear(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetWeekOfYearIso8601(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetDayOfMonth(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetDayOfWeek(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetDayOfWeekName(Resource<TM>{Flags:AutoMap}) -> String
DateTime::GetHour(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetMinute(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetSecond(Resource<TM>{Flags:AutoMap}) -> Uint8
DateTime::GetMillisecondOfSecond(Resource<TM>{Flags:AutoMap}) -> Uint32
DateTime::GetMicrosecondOfSecond(Resource<TM>{Flags:AutoMap}) -> Uint32
DateTime::GetTimezoneId(Resource<TM>{Flags:AutoMap}) -> Uint16
DateTime::GetTimezoneName(Resource<TM>{Flags:AutoMap}) -> String
Примеры
$tm = DateTime::Split(TzDatetime("2019-01-09T00:00:00,Europe/Moscow"));
SELECT
DateTime::GetDayOfMonth($tm) as Day, -- 9
DateTime::GetMonthName($tm) as Month, -- "January"
DateTime::GetYear($tm) as Year, -- 2019
DateTime::GetTimezoneName($tm) as TzName, -- "Europe/Moscow"
DateTime::GetDayOfWeekName($tm) as WeekDay; -- "Wednesday"
Update
Обновление одной или нескольких компонент во внутреннем представлении. Возвращает либо обновлённую копию, либо NULL, если после обновления получается некорректная дата или возникают другие противоречия.
Список функций
DateTime::Update( Resource<TM>{Flags:AutoMap}, [ Year:Uint16?, Month:Uint8?, Day:Uint8?, Hour:Uint8?, Minute:Uint8?, Second:Uint8?, Microsecond:Uint32?, Timezone:String? ]) -> Resource<TM>?
Примеры
$tm = DateTime::Split(Timestamp("2019-01-01T01:02:03.456789Z"));
SELECT
DateTime::MakeDate(DateTime::Update($tm, 2012)), -- 2012-01-01
DateTime::MakeDate(DateTime::Update($tm, 2000, 6, 6)), -- 2000-06-06
DateTime::MakeDate(DateTime::Update($tm, NULL, 2, 30)), -- NULL (30 февраля)
DateTime::MakeDatetime(DateTime::Update($tm, NULL, NULL, 31)), -- 2019-01-31T01:02:03Z
DateTime::MakeDatetime(DateTime::Update($tm, 15 as Hour, 30 as Minute)), -- 2019-01-01T15:30:03Z
DateTime::MakeTimestamp(DateTime::Update($tm, 999999 as Microsecond)), -- 2019-01-01T01:02:03.999999Z
DateTime::MakeTimestamp(DateTime::Update($tm, "Europe/Moscow" as Timezone)), -- 2018-12-31T22:02:03.456789Z (конвертация в UTC)
DateTime::MakeTzTimestamp(DateTime::Update($tm, "Europe/Moscow" as Timezone)); -- 2019-01-01T01:02:03.456789,Europe/Moscow
From...
Получение Timestamp из количества секунд/миллисекунд/микросекунд от начала эпохи в UTC. При выходе за границы Timestamp возвращается NULL.
Список функций
DateTime::FromSeconds(Uint32{Flags:AutoMap}) -> Timestamp
DateTime::FromMilliseconds(Uint64{Flags:AutoMap}) -> Timestamp
DateTime::FromMicroseconds(Uint64{Flags:AutoMap}) -> Timestamp
To...
Получение количества секунд/миллисекунд/микросекунд от начала эпохи в UTC из простого типа.
Список функций
DateTime::ToSeconds(Date/DateTime/Timestamp/TzDate/TzDatetime/TzTimestamp{Flags:AutoMap}) -> Uint32
DateTime::ToMilliseconds(Date/DateTime/Timestamp/TzDate/TzDatetime/TzTimestamp{Flags:AutoMap}) -> Uint64
DateTime::ToMicroseconds(Date/DateTime/Timestamp/TzDate/TzDatetime/TzTimestamp{Flags:AutoMap}) -> Uint64
Примеры
SELECT
DateTime::FromSeconds(1546304523), -- 2019-01-01T01:02:03.000000Z
DateTime::ToMicroseconds(Timestamp("2019-01-01T01:02:03.456789Z")); -- 1546304523456789
Interval...
Преобразования между Interval
и различными единицами измерения времени.
Список функций
DateTime::ToDays(Interval{Flags:AutoMap}) -> Int16
DateTime::ToHours(Interval{Flags:AutoMap}) -> Int32
DateTime::ToMinutes(Interval{Flags:AutoMap}) -> Int32
DateTime::ToSeconds(Interval{Flags:AutoMap}) -> Int32
DateTime::ToMilliseconds(Interval{Flags:AutoMap}) -> Int64
DateTime::ToMicroseconds(Interval{Flags:AutoMap}) -> Int64
DateTime::IntervalFromDays(Int16{Flags:AutoMap}) -> Interval
DateTime::IntervalFromHours(Int32{Flags:AutoMap}) -> Interval
DateTime::IntervalFromMinutes(Int32{Flags:AutoMap}) -> Interval
DateTime::IntervalFromSeconds(Int32{Flags:AutoMap}) -> Interval
DateTime::IntervalFromMilliseconds(Int64{Flags:AutoMap}) -> Interval
DateTime::IntervalFromMicroseconds(Int64{Flags:AutoMap}) -> Interval
Важно
Функция DateTime::ToSeconds
не поддерживает работу с интервалами с длительностью большей чем 68 лет, в этом случае можно использовать выражение DateTime::ToMilliseconds(x) / 1000
AddTimezone никак не влияет на вывод ToSeconds(), поскольку ToSeconds() всегда возвращают время в таймзоне GMT.
Interval также можно создавать из строкового литерала в формате ISO 8601.
Примеры
SELECT
DateTime::ToDays(Interval("PT3000M")), -- 2
DateTime::IntervalFromSeconds(1000000), -- 11 days 13 hours 46 minutes 40 seconds
DateTime::ToDays(cast('2018-01-01' as date) - cast('2017-12-31' as date)); --1
StartOf... / EndOf... / TimeOfDay
Получить начало (конец) периода, содержащего дату/время. При некорректном результате возвращается NULL. Если таймзона не GMT, то начало (конец) периода будет в указанной временной зоне.
Список функций
DateTime::StartOfYear(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOfYear(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::StartOfQuarter(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOfQuarter(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::StartOfMonth(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOfMonth(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::StartOfWeek(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOfWeek(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::StartOfDay(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOfDay(Resource<TM>{Flags:AutoMap}) -> Resource<TM>?
DateTime::StartOf(Resource<TM>{Flags:AutoMap}, Interval{Flags:AutoMap}) -> Resource<TM>?
DateTime::EndOf(Resource<TM>{Flags:AutoMap}, Interval{Flags:AutoMap}) -> Resource<TM>?
Функции StartOf
/EndOf
предназначены для группировки в пределах суток по произвольному периоду. Результат отличается от входного значения только компонентами времени. Период более суток трактуется как сутки (эквивалентно StartOfDay
/EndOfDay
). Если в сутках не содержится целого числа периодов, производится округление к ближайшему времени от начала суток, кратному указанному периоду. При нулевом интервале выход совпадает со входом. Отрицательный интервал трактуется как положительный.
Функции EndOf...
предназначены для получения последнего момента времени, находящегося в том же выбранном интервале, что и заданный.
Поведение функций с периодами больше дня отличается от поведения одноимённых функций в старой библиотеке. Компоненты времени всегда обнуляются (это логично, поскольку эти функции в основном используются для группировки по периоду). Отдельно существует возможность выделить время в пределах суток:
DateTime::TimeOfDay(Resource<TM>{Flags:AutoMap}) -> Interval
Примеры
SELECT
DateTime::MakeDate(DateTime::StartOfYear(Date("2019-06-06"))),
-- 2019-01-01 (неявный Split здесь и дальше)
DateTime::MakeDatetime(DateTime::StartOfQuarter(Datetime("2019-06-06T01:02:03Z"))),
-- 2019-04-01T00:00:00Z (компоненты времени обнулены)
DateTime::MakeDate(DateTime::StartOfMonth(Timestamp("2019-06-06T01:02:03.456789Z"))),
-- 2019-06-01
DateTime::MakeDate(DateTime::StartOfWeek(Date("1970-01-01"))),
-- NULL (начало эпохи - четверг, начало недели - 1969-12-29, выход за границы)
DateTime::MakeTimestamp(DateTime::StartOfWeek(Date("2019-01-01"))),
-- 2018-12-31T00:00:00Z
DateTime::MakeDatetime(DateTime::StartOfDay(Datetime("2019-06-06T01:02:03Z"))),
-- 2019-06-06T00:00:00Z
DateTime::MakeTzDatetime(DateTime::StartOfDay(TzDatetime("1970-01-01T05:00:00,Europe/Moscow"))),
-- NULL (в GMT выход за эпоху)
DateTime::MakeTzTimestamp(DateTime::StartOfDay(TzTimestamp("1970-01-02T05:00:00.000000,Europe/Moscow"))),
-- 1970-01-02T00:00:00,Europe/Moscow (начало дня по Москве)
DateTime::MakeDatetime(DateTime::StartOf(Datetime("2019-06-06T23:45:00Z"), Interval("PT7H"))),
-- 2019-06-06T21:00:00Z
DateTime::MakeDatetime(DateTime::StartOf(Datetime("2019-06-06T23:45:00Z"), Interval("PT20M"))),
-- 2019-06-06T23:40:00Z
DateTime::TimeOfDay(Timestamp("2019-02-14T01:02:03.456789Z"));
-- 1 hour 2 minutes 3 seconds 456789 microseconds
Shift...
Прибавить/вычесть заданное количество единиц к компоненте во внутреннем представлении и обновить остальные поля.
Возвращает либо обновлённую копию, либо NULL, если после обновления получается некорректная дата или возникают другие противоречия.
Список функций
DateTime::ShiftYears(Resource<TM>{Flags:AutoMap}, Int32) -> Resource<TM>?
DateTime::ShiftQuarters(Resource<TM>{Flags:AutoMap}, Int32) -> Resource<TM>?
DateTime::ShiftMonths(Resource<TM>{Flags:AutoMap}, Int32) -> Resource<TM>?
Если в результате номер дня в месяце превышает максимально возможный, то в поле Day
будет записан последний день месяца,
время при этом не изменится (см. примеры).
Примеры
$tm1 = DateTime::Split(DateTime("2019-01-31T01:01:01Z"));
$tm2 = DateTime::Split(TzDatetime("2049-05-20T12:34:50,Europe/Moscow"));
SELECT
DateTime::MakeDate(DateTime::ShiftYears($tm1, 10)), -- 2029-01-31T01:01:01
DateTime::MakeDate(DateTime::ShiftYears($tm2, -10000)), -- NULL (выход за границы)
DateTime::MakeDate(DateTime::ShiftQuarters($tm2, 0)), -- 2049-05-20T12:34:50,Europe/Moscow
DateTime::MakeDate(DateTime::ShiftQuarters($tm1, -3)), -- 2018-04-30T01:01:01
DateTime::MakeDate(DateTime::ShiftMonths($tm1, 1)), -- 2019-02-28T01:01:01
DateTime::MakeDate(DateTime::ShiftMonths($tm1, -35)), -- 2016-02-29T01:01:01
Format
Получить строковое представление момента времени, используя произвольную строку форматирования.
Список функций
DateTime::Format(String, alwaysWriteFractionalSeconds:Bool?) -> (Resource<TM>{Flags:AutoMap}) -> String
Для строки форматирования реализовано множество спецификаторов:
%%
- символ %;%Y
- год 4 цифры;%m
- месяц 2 цифры;%d
- день 2 цифры;%H
- час 2 цифры;%M
- минуты 2 цифры;%S
- секунды 2 цифры -- или xx.xxxxxx в случае непустых микросекунд (и только если флагalwaysWriteFractionalSeconds
не выставлен вTrue
);%z
- +hhmm or -hhmm;%Z
- IANA имя таймзоны;%b
- короткое трехбуквенное английское название месяца (Jan);%B
- полное английское название месяца (January).
Все остальные символы строки форматирования переносятся без изменений.
Примеры
$format = DateTime::Format("%Y-%m-%d %H:%M:%S %Z");
SELECT
$format(DateTime::Split(TzDatetime("2019-01-01T01:02:03,Europe/Moscow")));
-- "2019-01-01 01:02:03 Europe/Moscow"
Parse
Распарсить строку во внутреннее представление, используя произвольную строку форматирования. Для незаполненных полей используются значения по умолчанию. При возникновении ошибок возвращается NULL.
Список функций
DateTime::Parse(String) -> (String{Flags:AutoMap}) -> Resource<TM>?
Реализованные спецификаторы:
%%
- символ %;%Y
- год 4 цифры (1970);%m
- месяц 2 цифры (1);%d
- день 2 цифры (1);%H
- час 2 цифры (0);%M
- минуты 2 цифры (0);%S
- секунды (0), может принимать и микросекунды в форматах от xx. до xx.xxxxxx%Z
- IANA имя таймзоны (GMT).%b
- короткое трехбуквенное регистронезависимое английское название месяца (Jan);%B
- полное регистронезависимое английское название месяца (January).
Примеры
$parse1 = DateTime::Parse("%H:%M:%S");
$parse2 = DateTime::Parse("%S");
$parse3 = DateTime::Parse("%m/%d/%Y");
$parse4 = DateTime::Parse("%Z");
SELECT
DateTime::MakeDatetime($parse1("01:02:03")), -- 1970-01-01T01:02:03Z
DateTime::MakeTimestamp($parse2("12.3456")), -- 1970-01-01T00:00:12.345600Z
DateTime::MakeTimestamp($parse3("02/30/2000")), -- NULL (Feb 30)
DateTime::MakeTimestamp($parse4("Canada/Central")); -- 1970-01-01T06:00:00Z (конвертация в UTC)
Parse конкретных форматов
Для распространённых форматов есть врапперы вокруг соответствующих методов util. Можно получить только TM с компонентами в UTC таймзоне.
Список функций
DateTime::ParseRfc822(String{Flags:AutoMap}) -> Resource<TM>?
DateTime::ParseIso8601(String{Flags:AutoMap}) -> Resource<TM>?
DateTime::ParseHttp(String{Flags:AutoMap}) -> Resource<TM>?
DateTime::ParseX509(String{Flags:AutoMap}) -> Resource<TM>?
Примеры
SELECT
DateTime::MakeTimestamp(DateTime::ParseRfc822("Fri, 4 Mar 2005 19:34:45 EST")),
-- 2005-03-05T00:34:45Z
DateTime::MakeTimestamp(DateTime::ParseIso8601("2009-02-14T02:31:30+0300")),
-- 2009-02-13T23:31:30Z
DateTime::MakeTimestamp(DateTime::ParseHttp("Sunday, 06-Nov-94 08:49:37 GMT")),
-- 1994-11-06T08:49:37Z
DateTime::MakeTimestamp(DateTime::ParseX509("20091014165533Z"))
-- 2009-10-14T16:55:33Z
Типовые сценарии
Преобразования между строками и секундами
Преобразование строковой даты (в таймзоне Москвы) в секунды (в таймзоне GMT):
$datetime_parse = DateTime::Parse("%Y-%m-%d %H:%M:%S");
$datetime_parse_tz = DateTime::Parse("%Y-%m-%d %H:%M:%S %Z");
SELECT
DateTime::ToSeconds(TzDateTime("2019-09-16T00:00:00,Europe/Moscow")) AS md_us1, -- 1568581200
DateTime::ToSeconds(DateTime::MakeDatetime($datetime_parse_tz("2019-09-16 00:00:00" || " Europe/Moscow"))), -- 1568581200
DateTime::ToSeconds(DateTime::MakeDatetime(DateTime::Update($datetime_parse("2019-09-16 00:00:00"), "Europe/Moscow" as Timezone))), -- 1568581200
-- НЕПРАВИЛЬНО (Date импортирует время как GMT, а AddTimezone никак не влияет на ToSeconds, которая всегда возвращает время в таймзоне GMT)
DateTime::ToSeconds(AddTimezone(Date("2019-09-16"), 'Europe/Moscow')) AS md_us2, -- 1568592000
Преобразование строковой даты (в таймзоне Москвы) в секунды (в таймзоне Москвы). Поскольку DateTime::ToSeconds()
экспортирует только GMT, придется временно забыть о таймзонах и работать только в GMT (выглядит это так, как будто временно мы считаем, что в Москве таймзона GMT):
$date_parse = DateTime::Parse("%Y-%m-%d");
$datetime_parse = DateTime::Parse("%Y-%m-%d %H:%M:%S");
$datetime_parse_tz = DateTime::Parse("%Y-%m-%d %H:%M:%S %Z");
SELECT
DateTime::ToSeconds(Datetime("2019-09-16T00:00:00Z")) AS md_ms1, -- 1568592000
DateTime::ToSeconds(Date("2019-09-16")) AS md_ms2, -- 1568592000
DateTime::ToSeconds(DateTime::MakeDatetime($date_parse("2019-09-16"))) AS md_ms3, -- 1568592000
DateTime::ToSeconds(DateTime::MakeDatetime($datetime_parse("2019-09-16 00:00:00"))) AS md_ms4, -- 1568592000
DateTime::ToSeconds(DateTime::MakeDatetime($datetime_parse_tz("2019-09-16 00:00:00 GMT"))) AS md_ms5, -- 1568592000
-- НЕПРАВИЛЬНО (импортирует время в таймзоне Москвы, а RemoveTimezone никак не влияет на ToSeconds)
DateTime::ToSeconds(RemoveTimezone(TzDatetime("2019-09-16T00:00:00,Europe/Moscow"))) AS md_ms6, -- 1568581200
DateTime::ToSeconds(DateTime::MakeDatetime($datetime_parse_tz("2019-09-16 00:00:00 Europe/Moscow"))) AS md_ms7 -- 1568581200
Преобразование секунд (в таймзоне GMT) в строковую дату (в таймзоне Москвы):
$date_format = DateTime::Format("%Y-%m-%d %H:%M:%S %Z");
SELECT
$date_format(AddTimezone(DateTime::FromSeconds(1568592000), 'Europe/Moscow')) -- "2019-09-16 03:00:00 Europe/Moscow"
Преобразование секунд (в таймзоне Москвы) в строковую дату (в таймзоне Москвы). Здесь таймзона %Z
выводится для справки - обычно выводить ее не нужно, потому что она будет равна "GMT" и может сбить с толку.
$date_format = DateTime::Format("%Y-%m-%d %H:%M:%S %Z");
SELECT
$date_format(DateTime::FromSeconds(1568592000)) -- "2019-09-16 00:00:00 GMT"
Преобразование секунд (в таймзоне GMT) в трехбуквенное название дня недели (в таймзоне Москвы):
SELECT
SUBSTRING(DateTime::GetDayOfWeekName(AddTimezone(DateTime::FromSeconds(1568581200), "Europe/Moscow")), 0, 3) -- "Mon"
Форматирование даты и времени
Обычно для форматирования времени используется отдельное именованное выражение, но можно обойтись и без него:
$date_format = DateTime::Format("%Y-%m-%d %H:%M:%S %Z");
SELECT
-- Вариант с именованным выражением
$date_format(AddTimezone(DateTime::FromSeconds(1568592000), 'Europe/Moscow')),
-- Вариант без именованного выражения
DateTime::Format("%Y-%m-%d %H:%M:%S %Z")
(AddTimezone(DateTime::FromSeconds(1568592000), 'Europe/Moscow'))
;
Преобразование типов
Так можно преобразовывать только константы:
SELECT
TzDateTime("2019-09-16T00:00:00,Europe/Moscow"), -- 2019-09-16T00:00:00,Europe/Moscow
Date("2019-09-16") -- 2019-09-16
А так - константу, именованное выражение или поле таблицы:
SELECT
CAST("2019-09-16T00:00:00,Europe/Moscow" AS TzDateTime), -- 2019-09-16T00:00:00,Europe/Moscow
CAST("2019-09-16" AS Date) -- 2019-09-16
Преобразование времени в дату
CAST
в Date
или TzDate
дает такую дату в таймзоне GMT, в которую происходит полночь по локальному времени (например, для московского времени 2019-10-22 00:00:00, будет возвращена дата 2019-10-21). Для получения даты в локальной таймзоне можно использовать DateTime::Format.
$x = DateTime("2019-10-21T21:00:00Z");
select
AddTimezone($x, "Europe/Moscow"), -- 2019-10-22T00:00:00,Europe/Moscow
cast($x as TzDate), -- 2019-10-21,GMT
cast(AddTimezone($x, "Europe/Moscow") as TzDate), -- 2019-10-21,Europe/Moscow
cast(AddTimezone($x, "Europe/Moscow") as Date), -- 2019-10-21
DateTime::Format("%Y-%m-%d %Z")(AddTimezone($x, "Europe/Moscow")), -- 2019-10-22 Europe/Moscow
Стоит отметить, что некоторые значения в типaх TzDatetime и TzTimestamp, имеющие положительное смещение таймзоны, не могут быть преобразованы в тип TzDate. Рассмотрим следующий пример:
SELECT CAST(TzDatetime("1970-01-01T23:59:59,Europe/Moscow") as TzDate);
/* Fatal: Timestamp 1970-01-01T23:59:59.000000,Europe/Moscow cannot be casted to TzDate */
Не существует такого значения, начиная с Unix epoch, которым можно представить полночь 01.01.1970 для московского времени. В результате, такое преобразование считается невозможным и генерирует ошибку времени выполнения.
В то же время, значения, имеющие отрицательное смещение таймзоны, возвращают корректный результат:
SELECT CAST(TzDatetime("1970-01-01T23:59:59,America/Los_Angeles") as TzDate);
/* 1970-01-01,America/Los_Angeles */
Летнее время
Обратите внимание, что летнее время зависит от года:
SELECT
RemoveTimezone(TzDatetime("2019-09-16T10:00:00,Europe/Moscow")) as DST1, -- 2019-09-16T07:00:00Z
RemoveTimezone(TzDatetime("2008-12-03T10:00:00,Europe/Moscow")) as DST2, -- 2008-12-03T07:00:00Z
RemoveTimezone(TzDatetime("2008-07-03T10:00:00,Europe/Moscow")) as DST3, -- 2008-07-03T06:00:00Z (DST)