Как перевести дату в другой формат sas

Обновлено: 03.07.2024

Обработка различий между часовыми поясами становится все более важной для всех приложений, которые работают с датами и временем. Приложение больше не может считать, что все значения времени могут быть выражены в местном времени, которое является временем, доступным в DateTime структуре. Например, веб-страница, которая отображает текущее время в восточной части США, будет содержать недостоверные сведения для пользователей в восточной Азии. В этом разделе объясняется, как преобразовать время из одного часового пояса в другой, а также как преобразовать DateTimeOffset значения с ограниченной поддержкой часовых поясов.

Преобразование во время в формате UTC

Можно также сериализовать DateTimeOffset структуру для однозначного представления одного момента времени. Поскольку DateTimeOffset объекты хранят значение даты и времени вместе со смещением от времени в формате UTC, они всегда представляют определенный момент времени в связи с временем в формате UTC.

самый простой способ преобразовать время в формат UTC — вызвать static Shared метод (в Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime) . Точное преобразование, выполняемое методом, зависит от значения dateTime Kind Свойства параметра, как показано в следующей таблице.

DateTime.Kind Преобразование
DateTimeKind.Local Преобразует местное время во время в формате UTC.
DateTimeKind.Unspecified Предполагает, что параметр dateTime является местным временем и преобразовывает местное время в UTC.
DateTimeKind.Utc Возвращает неизмененный параметр dateTime .

Следующий код преобразовывает текущее местное время во время в формате UTC и выводит результат на консоль.

Если значение даты и времени не представляет ни местное время, ни время в формате UTC, то, ToUniversalTime скорее всего, метод вернет ошибочный результат. Однако можно использовать TimeZoneInfo.ConvertTimeToUtc метод для преобразования даты и времени из указанного часового пояса. (Дополнительные сведения о получении TimeZoneInfo объекта, представляющего часовой пояс назначения, см. в разделе Поиск часовых поясов, определенных в локальной системе.) В следующем коде используется TimeZoneInfo.ConvertTimeToUtc метод для преобразования восточного стандартного времени в формат UTC.

Обратите внимание, что этот метод создает исключение, ArgumentException Если DateTime Kind свойство объекта и часовой пояс не совпадают. Несоответствие возникает, если Kind свойство имеет значение DateTimeKind.Local TimeZoneInfo , но объект не представляет местный часовой пояс, или если свойство имеет значение, Kind DateTimeKind.Utc но объект не TimeZoneInfo равен TimeZoneInfo.Utc .

Все эти методы принимают DateTime значения в качестве параметров и возвращают DateTime значение. Для DateTimeOffset значений DateTimeOffset структура имеет ToUniversalTime метод экземпляра, который преобразует дату и время текущего экземпляра в формат UTC. В следующем примере вызывается ToUniversalTime метод для преобразования местного времени и нескольких других значений времени в формат UTC.

Преобразование времени в формате UTC в заданный часовой пояс

Для преобразования времени в формате UTC в местное время см. следующий раздел "преобразование времени UTC в местное время". Для преобразования времени в формате UTC во время в любом назначенном часовом поясе вызовите ConvertTimeFromUtc метод. Этот метод принимает два параметра:

Время в формате UTC, которое требуется преобразовать. Это должно быть DateTime значение, свойство которого равно Kind Unspecified или Utc .

Часовой пояс, в который требуется преобразовать время в формате UTC.

Следующий код преобразует время в формате UTC в центральное стандартное время.

Преобразование времени в формате UTC в местное время

Для преобразования времени в формате UTC в местное время вызовите ToLocalTime метод DateTime объекта, время которого необходимо преобразовать. Точное поведение метода зависит от значения Kind свойства объекта, как показано в следующей таблице.

DateTime.Kind Преобразование
DateTimeKind.Local Возвращает DateTime значение без изменений.
DateTimeKind.Unspecified Предполагается, что DateTime значение равно UTC и ПРЕОБРАЗУЕТ UTC в местное время.
DateTimeKind.Utc Преобразует DateTime значение в местное время.

TimeZone.ToLocalTimeМетод ведет себя идентично DateTime.ToLocalTime методу. Он принимает один параметр, который представляет собой значение даты и времени для преобразования.

можно также преобразовать время в любом заданном часовом поясе в местное время с помощью static Shared метода (в Visual Basic) TimeZoneInfo.ConvertTime . Этот метод рассматривается в следующем разделе.

Преобразование между любыми двумя часовыми поясами

преобразование между любыми двумя часовыми поясами можно выполнить с помощью любого из следующих двух static Shared методов (в Visual Basic) TimeZoneInfo класса:

Параметры этого метода — это значение даты и времени для преобразования, TimeZoneInfo объект, представляющий часовой пояс значения даты и времени, и TimeZoneInfo объект, представляющий часовой пояс для преобразования значения даты и времени в.

Параметры этого метода — это значение даты и времени для преобразования, идентификатор часового пояса значения даты и времени и идентификатор часового пояса, в который необходимо преобразовать значение даты и времени.

Для обоих методов требуется, Kind чтобы свойство значения даты и времени было преобразовано, а TimeZoneInfo объект или идентификатор часового пояса, представляющий его часовой пояс, соответствовал друг другу. В противном случае возникает исключение ArgumentException. Например, если Kind свойство значения даты и времени равно DateTimeKind.Local , возникает исключение, если TimeZoneInfo объект, переданный в качестве параметра в метод, не равен TimeZoneInfo.Local . Исключение также создается, если идентификатор, переданный в качестве параметра в метод, не равен TimeZoneInfo.Local.Id .

В следующем примере используется ConvertTime метод для преобразования из Гавайского стандартного времени в местное время.

Преобразование значений DateTimeOffset

Значения даты и времени, представленные DateTimeOffset объектами, не имеют полной осведомленности о часовых поясах, так как объект не связан с часовым поясом во время создания экземпляра. Однако во многих случаях приложению достаточно преобразовать дату и время на основе двух различных значений смещения относительно времени в формате UTC, а не на основе времени конкретных часовых поясов. Чтобы выполнить это преобразование, можно вызвать метод текущего экземпляра ToOffset . Единственным параметром метода является смещение нового значения даты и времени, возвращаемого методом.

Например, если дата и время запроса пользователя к веб-странице известны и сериализованы в виде строки в формате мм/дд/гггг чч:мм:сс zzzz, то следующий метод ReturnTimeOnServer преобразует это значение даты и времени в значение даты и времени на веб-сервере.

Если методу передается строка "9/1/2007 5:32:07 -05:00", которая представляет дату и время в часовом поясе, который раньше пояса UTC на пять часов, он возвращает строку "9/1/2007 3:32:07 -07:00" для сервера, расположенного в тихоокеанском стандартном часовом поясе США.

call missing(of x1-x2);

call missing (of _all_);

call missing (of _char_);

SAS может зачитывать даты практически любого формата, как, например, такие:

Дата Описание
10/21/1950 Month/Day/Year
21-10-1950 Day-Month-Year
21Oct1950 Day Month Abbreviation Year
50294 Julian Date

Однако все они хранятся в SAS как число, а именно, количество дней с 1 Января 1960 года (все даты, после этой – это положительные числа, до - отрицательные). Вот пример как в SAS хранятся даты:

Дата SAS значение
January 1, 1960 0
January 2, 1960 1
December 31, 1959 -1
June 15, 2006 16967
October 21, 1950 -3359

Давайте теперь познакомимся с некоторыми часто используемыми форматами для даты. Для этого рассмотрим следующий отрывок кода

Как мы уже с вами знаем, значение 1 в SAS соответствует дате 2 Января 1960. Однако, накладывая формат на переменную date, мы можем менять внешний вид этой даты. Давайте посмотрим на самые часто используемые форматы и то, как будет выглядеть одна и та же дата под разными форматами.

Название формата Результат
date9. 02JAN1960
date. 02JAN60
is8601da. 1960-01-02
ddmmyy10. 02/01/1960
ddmmyy8. 02/01/60
ddmmyy. 02/01/60
mmddyy10. 01/02/1960
mmddyy. 01/02/60
yymmdd6. 600102
yymmdd8. 60-01-02
yymmdd10. 1960-01-02

Особое внимание следует обратить на эти два формата: ddmmyy. и mmddyy. Бывают случаи, когда их можно перепутать. В частности, если в данных не встретилось дня больше 12, тогда сложно понять, что же тут день, а что месяц. В таких ситуациях, всегда лучше перестраховаться и уточнить.

Бывают случаи, когда вам нужно руками ввести какую-то определенную дату, чтобы что-то посмотреть, или проверить, или это какая-то значимая дата внутри проекта и вам нужно ее часто использовать и т.д. Например, это 06JUL1991. Согласитесь, навскидку и не скажешь сколько же это дней после 01JAN1960. Было бы странным, если бы SAS не оставил нам возможности ввести дату, как число, которое хранится в SAS, однако на понятном человеку языке. Я думаю, что было бы немало проблем, если всякий такой раз нужно было отдельно вычислять разницу с 01JAN1960 и вводить дату только как целое число. Для того, чтобы ввести дату, но чтобы SAS понял, что это именно дата, а не что-то другое, необходимо записать ее как date constant:

Давайте проверим, что же из этого получится.

Lesson2.3.1

Как видим, SAS распознал, что это дата и хранит ее как целое число. К сожалению, для date constant есть некоторые требования. Она обязательно должна выглядеть следующим образом: <1-2 цифры дня> <трехбуквенная аббревиатура месяца> <2 или 4 цифры года> в одинарных или двойных кавычках после чего d или D. Т.е. такую запись ‘01/06/1991’d SAS не распознает и в придачу ругнется на вас в логе.

А теперь давайте представим следующую ситуацию. Допустим, пациенту измерили давление в тот же день когда он принял исследуемый препарат. И представим даже, что давление это оказалось не совсем в норме. И вот тут вам важно очень знать, измерили давление до приема лекарства или после. Ведь если после, то, возможно, повышение давления связано именно с приемом этого лекарства. В таком случае вам нужно время замера и время приема лекарства. На практике, работать с датой/временем приходится очень часто, поэтому давайте поговорим о времени в SAS.

Посмотрим, чему соответствует 0, 1, 2 в SAS, наложи мы на него формат datetime16.

SAS значение Дата/Время
0 01JAN60:00:00:00
1 01JAN60:00:00:01
2 01JAN60:00:00:02

Как видим, мы уже имеем другие значения, не те, что были в примере с датами. Это говорит нам о том, что накладывая формат или делая какие-либо преобразования с датами, мы должны четко понимать, что именно хранится в переменной, иными словами, чему будет соответствовать единица – первой секунде первого января 60 года, или второму января 60 года.

После того, как мы убедились, что в нашей переменной хранится значение datetime, давайте посмотри, как будет выглядеть значение 20000 под разными форматами.

Название формата Результат
datetime. 01JAN60:05:33:20
datetime16. 01JAN60:05:33:20
datetime14. 01JAN60:05:33
is8601dt. 1960-01-01T05:33:20
dateampm. 01JAN60:05:33:20 AM
hhmm. 5:33
time. 5:33:20
time5. 5:33
is8601tm. 05:33:20
tod. 05:33:20
tod5. 05:33

Вполне естественно, что в SAS существуют некоторые функции, направленные на работу с датами/временем и только. Давайте познакомимся с некоторыми из них.

YRDIF(start-date, end-date, <basis>), где:

  • start-date – начальная дата
  • end-date – конечная дата
  • <basis> – опциональный аргумент, который указывает как именно считать эту разницу. Чаще всего используется 'ACT/ACT', который говорит SAS использовать реальное количество дней в каждом месяце, а также учитывать високосный год.

WEEKDAY(date), где:

day(date), где:

month(date), где:

year(date), где:

mdy(month,day,year), где:

  • month, day, year – числа либо переменные, задающие месяц, день и год

intck(interval,start-date,end-date), где:

  • interval – интересующий нас интервал, например, year, semi-year (полугодие), qtr (квартал), month, week, weekday (по умолчанию week без Sunday and Saturday)
  • start-date – начальная дата
  • end-date – конечная дата

Давайте рассмотрим несколько примеров того, как именно работает эта функция:

Expression Value Returned
intck('year', '01Jan2005'd, '31Dec2005’d) 0
intck ('year', '31Dec2005'd, '01Jan2006’d) 1
intck ('month', '01Jan2005'd, '31Jan2005'd) 0
intck ('month', '31Jan2005'd, '01Feb2005'd) 1
intck ('qtr', '25Mar2005'd, '15Apr2005'd) 1

Как мы видим, в первом случае intck вернет нам значение 0, т.к. обе даты – в пределах одного календарного года, в то время как во втором случае мы один раз пересекли границу интервала и в итоге получили значение 1. Аналогично с интервалами month и qtr.

Функция DATE_FORMAT преобразует дату из формата год-месяц-день или формата год-месяц-день часы:минуты:секунды в другой удобный нам формат.

К примеру, из год-месяц-день можно сделать день.месяц.год или месяц--год

См. также функцию TIME_FORMAT, которая меняет формат вывода времени.

Синтаксис

Команды

Можно использовать следующие команды, чтобы сделать нужный формат вывода:

Команда Описание
%d День месяца, число от 00 до 31.
%e День месяца, число от 0 до 31.
%m Месяц, число от 01 до 12.
%c Месяц, число от 1 до 12.
%Y Год, число, 4 цифры.
%y Год, число, 2 цифры.
%j День года, число от 001 до 366.
%H Час, число от 00 до 23.
%k Час, число от 0 до 23.
%h Час, число от 01 до 12.
%I Час, число от 01 до 12.
%l Час, число от 1 до 12.
%i Минуты, число от 00 до 59.
%S Секунды, число от 00 до 59.
%s Секунды, число от 00 до 59.
%w День недели (0 - воскресенье, 1 - понедельник).
%W Название дня недели по-английски.
%a Сокращенный день недели по-английски.
%M Название месяца по-английски.
%b Сокращенный месяц по-английски.
%D День месяца с английским суффиксом (1st, 2nd, 3rd и т.д.).
%r Время, 12-часовой формат (hh:mm:ss [AP]M).
%T Время, 24-часовой формат (hh:mm:ss).
%p AM или PM.
%U Неделя, где воскресенье считается первым днем недели, число от 00 до 53.
%u Неделя, где понедельник считается первым днем недели, число от 00 до 53.
%V Неделя, где воскресенье считается первым днем недели, число от 01 до 53.
Используется с `%X'.
%v Неделя, где понедельник считается первым днем недели, число от 01 до 53.
Используется с `%x'.
%X Год для недели, где воскресенье считается первым днем недели, число, 4 цифры.
Используется с '%V'.
%x Год для недели, где воскресенье считается первым днем недели, число, 4 разряда.
Используется с '%v'.
%% Символ `%'.

Примеры

Все примеры будут по этой таблице workers, если не сказано иное:

id
айди
name
имя
date
дата регистрации
1 Дима 2010-03-01 12:01:02
2 Петя 2011-04-02 13:02:03
3 Вася 2012-05-03 14:03:04

Пример

В данном примере при выборке создается новое поле, в котором будет лежать дата в другом формате:

Новая рубрика. Перевод небольших учебных пособий SAS Tips, публикующихся экспертами SAS в официальных блогах на английском. Есть интересные и полезные уроки

Начнем с туториала по функциям INTCK и INTNX. Урок построен на примере президентов США, ну так и писал американский эксперт Rick Wicklin :)

INTCK и INTNX: Две важные функции для вычисления интервалов между датами в SAS

На прошлой неделе я продемонстрировал временную шкалу для здравствующих президентов США. Число здравствующих президентов постоянно в течение временного интервала между датами инаугурации и датами смерти президентов. Данные были взяты из таблицы в Википедии (приведена ниже), в которой показано количество лет и дней между событиями. В этой статье описано, как использовать функции INTCK и INTNX в SAS для вычисления времени между событиями в этом формате. В частности, я использую два малоизвестных варианта этих функций, которые облегчают эту задачу

Интервалы между датами

Если вы вычисляете интервал между двумя датами (датой начала и датой окончания), есть две функции SAS, о которых вы обязательно должны знать.

  • Функция INTCK возвращает количество единиц времени между двумя датами. В качестве единицы времени можно выбрать годы, месяцы, недели, дни и многое другое. Например, в своей предыдущей статье я использовал функцию INTCK для определения количества дней между двумя датами.
  • Функция INTNX возвращает дату SAS, которая отстоит от указанной даты на указанное количество единиц времени. Например, функцию INTNX можно использовать для вычисления даты, которая находится на 308 дней позже указанной даты.

Две эти функции дополняют друг друга: одна вычисляет разницу между двумя датами, а другая позволяет добавлять единицы времени к значению даты.

По умолчанию эти функции используют количество "календарных границ" между датами, таких как первый день года, месяц или неделя. Например, если вы хотите измерить годовые интервалы, то функция INTCK подсчитывает, сколько раз происходило 1 января (01JAN) между датами, а функция INTNX возвращает дату будущего 1 января (01JAN). Аналогично, если вы измеряете месячные интервалы, то функция INTCK подсчитывает, сколько первых дней месяцев произошло между двумя датами, а функция INTNX возвращает будущую дату первого числа месяца.

Параметры для подсчета годовщин

Обе функции поддерживают множество параметров. Если вы хотите рассчитать количество полных годовых интервалов, а не просто количество канунов нового года, можно воспользоваться параметрами этих функций (начиная с SAS 9.2) для подсчета количества годовщин между двумя датами и вычисления даты будущей годовщины. Вы можете использовать параметр "CONTINUOUS" для функции INTCK и параметр "SAME" для функции INTNX следующим образом:

Параметр "CONTINUOUS" для функции INTCK позволяет подсчитать количество годовщин одной даты, которые произошли до наступления второй даты. Например, выражение

Years = intck('year', '30APR1789'd, '04MAR1797'd, 'continuous');

возвращает значение 7, потому что между этими двумя датами существует 7 полных лет (годовщин 30 апреля). Без параметра "CONTINUOUS" функция возвращает 8, потому что 1 января (01JAN) происходит 8 раз между этими датами.

Anniv = intnx('year', '30APR1789'd, 7, 'same');

возвращает 7-ю годовщину даты 30APR1789. Другими словами, он возвращает 30APR1796.

Прелесть этих функций заключается в том, что они автоматически обрабатывают високосные годы! Если вы запрашиваете количество дней между двумя датами, функция INTCK включает в себя високосные дни. Если событие происходит в високосный день, и вы определяете следующую годовщину этого события с помощью функции INTNX, вы получите 28 февраля (28FEB) следующего года (это наиболее распространенная схема для годовщин с високосными днями).

Алгоритм вычисления количества лет и дней между событиями

Следующий алгоритм вычисляет количество лет и дней между датами в SAS:

  • Используйте функцию INTCK с параметром "CONTINUOUS", чтобы вычислить количество полных лет между двумя датами.
  • Используйте функцию INTNX, чтобы найти третью дату (дату годовщины), которая совпадает с начальной датой по месяцу и дню, но происходит за год до конечной даты. (Годовщина для високосных дней – это 28FEB или 29FEB, в зависимости от того, происходит ли годовщина в високосном году.)
  • Используйте функцию INTCK для вычисления количества дней между датой годовщины и датой окончания.

На следующем этапе вычисляем временной интервал в годах и днях между датами инаугурации и датами смерти для нескольких первых президентов США. Полученные переменные Year и Day содержат ту же информацию, что и в таблице Википедии.

Выводы и ссылки

Таким образом, функции INTCK и INTNX незаменимы для вычисления интервалов между датами. В этой статье я подчеркнул важность двух малоизвестных параметров этих функций: параметра "CONTINUOUS" в INTCK и параметра "SAME" в INTNX. Используя эти параметры, вы можете рассчитать количество годовщин между датами и последнюю годовщину. Таким образом, вы можете рассчитать количество лет и дней между двумя датами.

Об определении дат и интервалов между датами в SAS написано множество статей. Я рекомендую следующие статьи:

  • Краткое введение в функции даты и времени SAS – статья Andrew Karp (2003) "Working with SAS Date and Time Functions." К сожалению, эта статья была написана до того, как были добавлены параметры "CONTINUOUS" и "SAME".
  • Я узнал о параметре "SAME" из короткой статьи Bruce Gilsen (2006) "Improve Your Dating: The INTNX Function Alignment Value SAMEDAY."
  • Более подробную статью с массой примеров, включая примеры использования параметров "CONTINUOUS" и "SAME", написал Derek Morgan (2015) "Demystifying Date and Time Intervals." Derek также написал книгу The Essential Guide to SAS Dates and Times (Second Edition, 2014)

И наконец, знаете ли вы, что означают аббревиатуры INTCK и INTNX? Очевидно, что часть "INT" относится к слову INTervals ("интервалы"). По общему мнению, "INTCK" означает "Interval Check" (проверка интервала), а "INTNX" – "Interval Next" (следующий интервал).

Читайте также: