Для представления даты и времени в PowerShell используется тип DateTime, позволяющий сравнивать различные значения и производить над ними различные действия. Но иногда необходимо обработать данные, содержащие дату и время в обычном текстовом формате. Подобные операции приходится производить, к примеру, при парсинге логов приложений.
В этом случае придется предварительно сконвертировать строку текста в тип DateTime. А поскольку разные приложения пишут дату в логах в совершенно разных, порой нестандартных форматах, то при их обработке может возникнуть проблема.
Проще всего взять исходную строку и явно указать для нее тип данных, например так:
[datetime] ″07-13-2014 18:30:23″
Но тут есть одна тонкость — дата должна быть строго в определенном формате. Если точнее, то в американском (US), т.е. вида MM/dd/yyyy HH:mm:ss.ffff (месяц/число/год часы:минуты:секунды.миллисекунды). Это не зависит от текущих региональных настроек системы, по умолчанию формат DateTime всегда американский.
Возможно это было сделано для того, чтобы скрипты не зависели от региональных настроек и одинаково выполнялись на различных системах. Поэтому, если исходная строка не подходит под нужный формат, то мы получим либо неправильный результат, либо ошибку.
Для разбора времени\даты в соответствии с региональными настройками можно воспользоваться статическими методами .Net класса DateTime. Выведем список статических свойств и методов командой:
[DateTime] | Get-Member -Static
Здесь нас интересуют методы Parse и ParseExact, предназначенные для парсинга даты, а также TryParse и TryParseExact — для проверки валидности входных данных.
Примечание. Обычные свойства и методы — это свойства и методы, принадлежащие конкретному объекту, и для обращения к ним необходимо сначала этот объект создать. Статические же свойства и методы не требуют создания объекта для того, чтобы работать с ним.
Для разбора даты в соответствии с текущими региональными настройками воспользуемся методом parse:
[datetime]::parse(″13-07-2014 18:30:23″)
Если же данные представлены в формате, отличном от текущего, то можно воспользоваться методом parseexact. Для стандартных форматов даты\времени можно указать один из предопределенных типов, например:
[datetime]::parseexact(‘2014-07-13T18:30:23.3494995+04:00’, ′o′, $null)
Если же ни один из стандартных форматов не подходит, то можно указать маску, по которой будет производиться разбор даты, к примеру так:
[datetime]::parseexact(‘13072014-18~30~23’, ‘ddMMyyyy-HH~mm~ss’, $null)
Ну и если надо предварительно выяснить, содержит ли строка данные типа DateTime, то можно воспользоваться методами TryParse и TryParseExact. Для стандартных форматов подойдет TryParse:
$d = New-Object DateTime
[datetime]::tryparse(‘13.07.2014 18:30:23’, [ref]$d)
А для нестандартных — TryParseExact:
$d = New-Object DateTime
[datetime]::tryparseexact(‘130720014-18~30~23’, ‘ddMMyyyy-HH~mm~ss’, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimestyles]::None, [ref]$d)
Вот как то так 🙂
Последний пример почему-то упорно выдаёт False. Проверено на PowerShell 5.1 и 7.2.
Столкнулся ещё с тем, что формат ‘2010:05:16 18:32:57’ отказывается парсить. Если строку разделить, то хорошо. Если заменить первые два двоеточия на точки, то тоже в порядке. А вот в таком виде вместе — ошибка.