Парсинг дат и времени

Практически все значения дат и времени в PowerShell представлены в виде DateTime. Это класс .Net, позволяющий легко сравнивать различные значение и производить с ними различные операции.

Однако зачастую приходится обрабатывать источники данных в которых значения времени представлены в виде простого текста — например логи. И так уж сложилось, что у различных разработчиков есть разные взгляды на то как следует записывать время в текстовом виде. И тут возникает вопрос — как разобрать эту строку, и сконвертировать её в тип DateTime? В посте про оператор -replace я уже показывал один из вариантов как это можно сделать. Но честно говоря тот способ несколько…. не «прямой». 😉 А проблема часто возникающая. Так что я решил более подробно рассмотреть эту тему.

Начнем с простейшего. PowerShell (или .Net) может легко сконвертировать текстовую строку в тип DateTime если время в этой строке написано в определённом формате. А точнее в американском, например «2/22/2008 23:12:33.1233», короче говоря — «месяц/число/год часы:минуты:секунды.миллисекунды».

[PS <19> C:\Root] [datetime]"2/22/2008 23:12:33.1233"
22 февраля 2008 г. 23:12:33

[PS <20> C:\Root] [datetime]"2/22/2008 23:12:33.1233" | format-list *
DateTime    : 22 февраля 2008 г. 23:12:33
Date        : 22.02.2008 0:00:00
Day         : 22
DayOfWeek   : Friday
DayOfYear   : 53
Hour        : 23
Kind        : Unspecified
Millisecond : 123
Minute      : 12
Month       : 2
Second      : 33
Ticks       : 633393187531233000
TimeOfDay   : 23:12:33.1233000
Year        : 2008

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

Если всё же необходимо разобрать дату в соответствии с региональными настроками, то следует использовать статический метод Parse класса DateTime:

[PS <21> C:\Root] [datetime]::parse("22/2/2008 23:12:33.1233")
22 февраля 2008 г. 23:12:33

В обоих случаях, в строке не обязательно должны присутствовать все элементы. Можно указать только дату, только время, или например не указывать милисекунды.

[PS <22> C:\Root] [datetime]"2/22/2008"
22 февраля 2008 г. 0:00:00

[PS <23> C:\Root] [datetime]"23:12:33"
2 июля 2008 г. 23:12:33

[PS <24> C:\Root] [datetime]"23:12"
2 июля 2008 г. 23:12:00

[PS <25> C:\Root] [datetime]::parse("22/2/2008")
22 февраля 2008 г. 0:00:00

Как видно из примеров, если не указана дата, то будет подставлен текущий день, а в случае отсутствия времени подставится 0:00:00.

Ну и вернёмся к первоначальной задаче. Как разобрать дату если она записана в каком то ином формате. Тут понадобится метод ParseExact (спасибо MoW за подсказку 😉 ). Он позволяет указать любой свой формат для разбора строки в дату.

[PS <26> C:\Root] [datetime]::ParseExact('11222008-13~44~14','MMddyyyy-ss~mm~HH',$null)
22 ноября 2008 г. 14:44:13

В качестве первого параметра указывается разбираемая строка, а второй параметр — маска по которой будет происходить разбор. MM — означает 2 цифры месяца, dd — 2 цифры дня, yyyy — 4 цифры года, ss — секунды, mm — минуты, HH — часы в 24-часовом формате (для 12 часового используется hh). Подробнее про возможные символы и их значения можно прочитать тут. Кстати еще есть возможность не вводить маску полностью самому, а использовать предопределенные:

[PS <27> C:\Root] [datetime]::ParseExact('Wed, 02 Jul 2008 12:27:01 GMT','r',$null)
2 июля 2008 г. 12:27:01

Приятного парсинга логов 😉

Опубликовано в Learn, PowerShell, Scripting, Tips. 1 Comment »

Один ответ to “Парсинг дат и времени”

  1. Сдвиг субтитров « PowerShell и другие скрипты Says:

    […] на приемы работы с датами которые я тут использовал: ParseExact и оператор […]


Обсуждение закрыто.