Форматы времени и даты в PowerShell
Для получения даты и времени в PowerShell существует командлет Get-Date. Выполнив команду Get-Date, мы получим текущее время и дату в полном формате. Вот так выглядит стандартный вывод даты в английском (US) стандарте:
В принципе вывод достаточно информативен, но иногда может понадобиться получить дату в формате, отличном от дефолтного. Нет проблем, при необходимости формат вывода можно легко изменить множеством различных способов. Наиболее простой — это использовать стандартные форматы даты и времени, приведенные в таблице.
Параметр | Формат времени\даты | Пример вывода |
d | Короткий формат даты (ShortDatePattern) | 7/2/2014 |
D | Длинный формат даты (LongDatePattern) | Wednesday, July 2, 2014 |
f | Полная дата и время (long date and short time) | Wednesday, July 2, 2014 12:50 AM |
F | Полная дата и время (long date and long time) | Wednesday, July 2, 2014 12:50:49 AM |
g | General (short date and short time) | 7/2/2014 12:50 AM |
G | General (short date and long time) | 7/2/2014 12:50:49 AM |
m, M | День и месяц (MonthDayPattern) | July 2 |
o | Round-trip date/time pattern | 2014-07-02T12:50:49.3494995+04:00 |
r, R | RFC1123Pattern | Wed, 02 Jul 2014 12:50:49 GMT |
s | SortableDateTimePattern (based on ISO 8601) | 2014-07-02T12:50:49 |
t | Короткий формат времени (ShortTimePattern) | 12:50 AM |
T | Длинный формат времени (LongTimePattern) | 12:50:49 AM |
u | Универсальный формат (UniversalSortableDateTimePattern) | 2014-07-02 11:21:50Z |
U | Полная дата и время (long date and long time) в UTC | Wednesday, July 1, 2014 08:50:52 PM |
y, Y | Год и месяц (YearMonthPattern) | July, 2014 |
Для использования формата надо указать нужное значение с помощью параметра Format. Например так мы получим дату в коротком варианте:
Get-Date -Format d
Так выведем только год и месяц:
Get-Date -Format y
Или только время:
Get-Date -Format T
А так посмотрим дату\время по UTC:
Get-Date -Format U
Если же стандартных форматов недостаточно, то вывод даты\времени можно кастомизировать с помощью пользовательских параметров. Их довольно много, вот наиболее употребимые.
Параметр | Описание |
d, %d | День месяца в цифровом формате (1-31), без добавления лидирующего нуля. |
dd | День месяца в цифровом формате (01-31), с добавлением лидирующего нуля. |
ddd | Название дня недели, короткий вариант (напр. Sun). |
dddd | Название дня недели, полный вариант. |
h, %h | Часы в 12-часовом варианте (1-12) без добавления лидирующего нуля. |
hh | Часы в 12-часовом варианте (01-12) с добавлением лидирующего нуля. |
H, %H | Часы в 24-часовом варианте (0-23) без добавления лидирующего нуля. |
HH | Часы в 24-часовом варианте (00-23) с добавлением лидирующего нуля. |
m, %m | Минуты, без добавления лидирующего нуля. |
mm | Минуты, с добавлением лидирующего нуля. |
M, %M | Месяц в цифровом формате (1-12) без добавления лидирующего нуля. |
MM | Месяц в цифровом формате (01-12) с добавлением лидирующего нуля. |
MMM | Название месяца, сокращенный вариант (напр. Jul). |
MMMM | Название месяца, полный вариант. |
s, %s | Секунды, без добавления лидирующего нуля. |
ss | Секунды, с добавлением лидирующего нуля. |
f,ff,fff,ffff | Миллисекунды. |
t, %t | Переключатель AM/PM (первая буква). |
tt | Переключатель AM/PM. |
y, %y | Год без указания тысячелетия. Если год меньше 10, лидирующий ноль не добавляется (напр. 8). |
yy | |
yyyy | Год, полный формат. |
z, %z | Часовая зона, короткий формат (напр. +4). |
zz | Часовая зона, короткий формат (напр. +04). |
zzzz | Часовая зона, полный формат (напр. +04:00). |
g | Эра, до\после НЭ. |
Знак процента (%) в указании параметра следует добавлять, если параметр используется сам по себе, а не в сочетании с другими параметрами.
Если необходимо добавить в вывод какую либо текстовую информацию, то можно использовать обратный слэш (\). Поставленный в начале он позволяет интерпретировать символы не как параметры, а как обычные буквы. Если же вы хотите использовать слэш как разделитель, то его надо экранировать, используя двойной слэш (\\).
Пользовательские настройки позволяют получить дату\время в любом удобном виде, например так:
Get-Date -Format dd.MM.yyyy
Или так:
Get-Date -Format ″dd MMMM yyyy HH:mm:ss″
И даже так:
Get-Date -Format ″dd MMMM yyyy HH:mm:ss.ffff zzzz g″
Но и это не все. У командлета Get-Date есть еще один параметр UFormat, для вывода даты в Unix-формате.
Параметр | Описание |
с | Дата и время, с сокращениями (Wed Jul 2 12:50:49 2014) |
D | Короткий формат даты (7/2/2014) |
С | Век (21). |
у, g | Год в двузначном формате (14) |
Y, G | Год в четырехзначном формате (2014) |
b, h | Месяц, короткое название (Jul) |
B | Месяц, полное название (July) |
m | Номер месяца в двузначном формате (07) |
U, W | Номер недели в году (00-52) |
V | Номер недели в году (01-53) |
a | День недели, сокращенное название (Sun) |
A | День недели, полное название (Sundy) |
u, w | Номер дня недели, начиная с понедельника (1-7) |
d | День месяца в двузначном формате (07). |
e | День месяца в формате пробел+однозначное число ( 07). |
j | Номер дня в году (1-366). |
p | Переключатель AM\PM. |
r | Время в 12-часовом формате |
R | Время в 24-часовом формате, без секунд |
T, X | Время в 24-часовом формате, полный вариант |
Z | Смещение относительно UTC (+04). |
H, k | Час в 24-часовом формате (00-23) |
I, l | Час в 12-часовом формате (01-12) |
M | Минуты (01-60) |
S | Секунды (01-60) |
s | Число секунд, прошедших с 1 января 1970 года |
При использовании UFormat перед каждым значением необходимо ставить знак %, например так:
Get-Date -UFormat ″%A %d %B %r″
UFormat интересен тем, что можем получить довольно нестандартные варианты, например номер дня:
Get-Date -UFormat %j
Или недели в году:
Get-Date -UFormat %j
И даже количество времени в секундах, прошедшее с 00 часов 00 минут 00 секунд 1 января 1970 года (начало отсчета времени для UNIX-систем):
Get-Date -UFormat %s
Как видите, вариантов вывода море, есть из чего выбрать. И в завершение напомню, что формат вывода времени\даты зависит от региональных настроек, изменить которые можно из панели управления.
На этом все, а в следующий раз рассмотрим варианты преобразования текстовых строк в формат даты\время.
windowsnotes.ru
Get-Date — примеры работы с датой в Powershell
Get-Date возвращает в Powershell дату и время. С помощью этого командлета мы можем получить нужное нам значение формата Datetime, что поможет нам выполнять, например, сравнение дат.
Т.е. выполнение команды без ключей вернет нам текущую дату в powershell:
Get-Date
Если нам нужно получить какую-то другую дату формата Datetime, то надо установить ее с помощью этого команды:
Get-Date -Year 2030 -Month 8 -Day 9 -Hour 10 -Minute 11 -Second 12
Если мы не установим какое-то значение, например Year (год), то он возьмется текущий.
Навигация по статье:
Прибавление у убавление в дате
Преобразование в строку и из строки
Форматирование даты
Другие примеры работ
Получим свойства и методы этого объекта:
Get-Date | Get-Member
Все методы — это то что мы можем сделать с датой. Для примера получим дату минус один день от сегодняшнего числа:
(Get-Date).AddDays(-1)
Или прибавить дни через AddDays:
$result = (Get-Date).AddDays(365)
Если мы прибавим, допустим, часы больше чем в сутках, то у нас изменится и день:
$result = (Get-Date).AddHours(30)
Таким же образом мы можем добавлять и убирать такие элементы дат:
- AddDays — дни
- AddHours — часы
- AddMilliseconds — миллисекунды
- AddMinutes — минуты
- AddMonths — месяца
- AddSeconds — секунды
- AddYears — года
Так же как и во всех других языках мы можем преобразовать тип даты. Для того что бы преобразовать в строку у нас есть несколько методов:
- ToLongDateString — строка с днем недели и именем месяца
- ToLongTimeString — показывает часы, минуты и время
- ToShortDateString — возвращает только дату
- ToShortTimeString — вернет только часы и минуты
- ToString — вернут полную дату и время
Каждый из этих методов вызывается так:
(Get-Date).ToLongDateString()
Или на примере какой-то другой даты с переменной:
$yesterday = Get-Date -Month 6 -Year 2225
$yesterday.ToLongDateString()
Для того что бы получить дату из строки нужно использовать ключ date:
Get-Date -Date "1/1/2019"
Если мы не установим время или дату, то значение возьмется текущее:
Get-Date -Date "10:15"
Нужно учитывать, что формат даты в таком варианте исполнения будет тем, который установлен в системных настройках. В моем случае американский и поэтому идет месяц, день, год. Если стоит русский будет день, месяц и год. Увидеть эту настройку можно так:
Get-WinSystemLocale
Возможно получить только день недели или час от времени и для этого нужно использовать Format или один из методов. Так я получу год:
Get-Date -Format "yyyy"
Или аналогично, но уже используя свойство:
(Get-Date).year
Используя Format всегда возвращается тип данных string, а не DateTime.
У нас есть еще множество свойств, кроме Year, которые мы можем получать:
Выведем день недели ( DayOfWeek):
(Get-Date).DayOfWeek
Обратите внимание, что не всегда возвращаемый объект типа DateTime. Он может быть и численным (int) или строковым, в случае с Format.
На примере Format есть много спецификаторов:
- dddd — день недели в виде имени
- MM — номер месяца
- dd — день месяца
- yyyy — год
- HH:mm — часы и минуты
- K — Часовой пояс
- ss — секунды
Так мы выведем дату формата часы, минуты, день, месяц и год:
Get-Date -Format "HH:mm dd/MM/yyyy"
Обращаете внимание на регистр иначе получим другие значение.
Выполнять сравнение дат можно в случае, если значение типа DateTime. Какого типа значение мы можем посмотреть двумя способами. При просмотра свойства объекта мы увидим какого типа он возвращает значение:
Get-ChildItem | Get-Member | Where-Object -Property Definition -Like "*datetime*"
Либо у получить это значение так:
(Get-Date).GetType()
Для примера сравним в powershell даты файла. На картинке выше видно, что у каждого файла есть свойство CreationTime формата DateTime. Сравним какие файлы были созданы за последние 15 дней:
Get-ChildItem -Path ".\Folder2\" | where -Property CreationTime -GT (Get-Date).AddDays(-15)
GT — говорит о том, что мы ищем значения только больше чем справа. Обо всех операторах сравнения мы говорили тут.
Мы можем сравнивать и только по дню месяца, но в случае ниже день месяца будет числом, а не датой:
Get-ChildItem -Path C:\Folder2\ | Where-Object {$_.CreationTime.Day -eq (Get-Date).Day}
Командлет Get-ChildItem мы рассматривали тут.
Один из интересных примеров в работе с датой это командлет New-TimeSpan, который вернет время работы сервиса или любого другого объекта, если передать ему время. Для примера так он вернет значение в минутах, секундах с установленной даты:
New-TimeSpan -Start (Get-Date).AddDays(-15)
Применение этому можно найти, например, открытым пользователями через SMB файлам или очень долго запущенным процессам.
На примере процессов:
…Теги: #powershell
fixmypc.ru
Formatting Date Strings with PowerShell
Dr Scripto
Summary: Microsoft Scripting Guy, Ed Wilson, talks about formatting date strings with Windows PowerShell.
Microsoft Scripting Guy, Ed Wilson, is here. It seems that different ways to display dates and times are in great supply. In fact, there are dozens of ways to do this. If I decide that I do not like the way a date or time displays, I can change it. In addition, the way a particular date style displays in one country is different than the way it displays in another country.
These differences are part of the culture settings. For example, the output from the Get-Date cmdlet appears differently depending on the UI culture settings. Here is an example:
PS C:> Use-Culture de-de {get-date}
Mittwoch, 21. Januar 2015 12:23:40
PS C:> Get-Date
Wednesday, January 21, 2015 12:23:45 PM
Note The Use-Culture function is not standard in Windows PowerShell or Windows. It comes from Lee Holmes’
PowerShell Cookbook module. I installed it from the PowerShell Gallery, but it is also available on PoshCode.
In general, I want the date to automatically change the way it displays based on culture settings because it helps avoid confusion. There may be times when I want to override this behavior. I can do this by directly formatting the date. I can use the ToString method and specify the display pattern. The pattern MM – dd –yyyy specifies that I want the month, day, and year to appear in that order. The MM is case sensitive. Here is an example:
PS C:> (Get-Date -Month 2 -Day 12 -Year 2015).tostring(“MM-dd-yyyy”)
02-12-2015
There can be a very real problem with this technique. In many regions, the day value comes first. So is the month February or is it December? Here is how the date displays when I use German UI culture settings:
PS C:> Use-Culture de-DE {(Get-Date -Month 2 -Day 12 -Year 2015).tostring(“MM-dd-yyyy”)}
02-12-2015
According to their pattern, this is December 2, 2015. Here is the short date pattern:
PS C:> [System.Globalization.CultureInfo]::GetCultureInfo(1031).DateTimeFormat.ShortDatePattern
dd.MM.yyyy
Now the culture settings use a hexadecimal value from the National Language Support API. Germany uses a hex value of 0x0407. If I convert it to a decimal format, it becomes 1031. This is shown here:
PS C:> 0x0407
1031
I double check that I have the correct language settings by using the GetCulturalInfo static method:
PS C:> [System.Globalization.CultureInfo]::GetCultureInfo(1031)
LCID Name DisplayName
—- —- ———–
1031 de-DE German (Germany)
So if I really want to display a short date, I need to use a format specifier to tell Windows PowerShell to display a short date. In this way, it will be culture specific. On the MSDN page, Standard Date and Time Format Strings, I learn that the .NET short date specifier is “d”. So, I use the –format parameter of Get-Date, and the following appears:
PS C:> get-date -Format d
1/21/2015
But what about using a different culture? Well, this is how it displays in culture de-DE:
PS C:> Use-Culture de-DE {get-date -Format d}
21.01.2015
As a best practice, I should avoid creating my own date format strings if at all possible. If I use the built-in .NET date format specifiers, Windows PowerShell automatic displays it in the correct format. Here is a table of the .NET date format specifiers.
Format Specifier | Description | Examples |
d | Short date pattern | 2009-06-15T13:45:30 -> 6/15/2009 en-US 2009-06-15T13:45:30 -> 15/06/2009 fr-FR 2009-06-15T13:45:30 -> 2009/06/15 ja-JP |
D | Long date pattern | 2009-06-15T13:45:30 -> Monday, June 15, 2009 en-US 2009-06-15T13:45:30 -> 15 июня 2009 г. ru-RU 2009-06-15T13:45:30 -> Montag, 15. Juni 2009 de-DE |
f | Full date pattern with short time pattern | 2009-06-15T13:45:30 -> Monday, June 15, 2009 1:45 PM en-US 2009-06-15T13:45:30 -> den 15 juni 2009 13:45 sv-SE 2009-06-15T13:45:30 -> Δευτέρα, 15 Ιουνίου 2009 1:45 μμ el-GR |
F | Full date pattern with long time pattern | 2009-06-15T13:45:30 -> Monday, June 15, 2009 1:45:30 PM en-US 2009-06-15T13:45:30 -> den 15 juni 2009 13:45:30 sv-SE 2009-06-15T13:45:30 -> Δευτέρα, 15 Ιουνίου 2009 1:45:30 μμ el-GR |
g | General date pattern with short time pattern | 2009-06-15T13:45:30 -> 6/15/2009 1:45 PM en-US 2009-06-15T13:45:30 -> 15/06/2009 13:45 es-ES 2009-06-15T13:45:30 -> 2009/6/15 13:45 zh-CN |
G | General date pattern with long time pattern | 2009-06-15T13:45:30 -> 6/15/2009 1:45:30 PM en-US 2009-06-15T13:45:30 -> 15/06/2009 13:45:30 es-ES 2009-06-15T13:45:30 -> 2009/6/15 13:45:30 zh-CN |
M, m | Month/day pattern | 2009-06-15T13:45:30 -> June 15 en-US 2009-06-15T13:45:30 -> 15. juni da-DK 2009-06-15T13:45:30 -> 15 Juni id-ID |
O, o | Round-trip date/time pattern | 2009-06-15T13:45:30 –> 2009-06-15T13:45:30.0000000-07:00 2009-06-15T13:45:30 –> 2009-06-15T13:45:30.0000000Z 2009-06-15T13:45:30 2009-06-15T13:45:30.0000000 2009-06-15T13:45:30-07:00 –> 2009-06-15T13:45:30.0000000-07:00 |
R, r | RFC1123 pattern | 2009-06-15T13:45:30 -> Mon, 15 Jun 2009 20:45:30 GMT |
s | Sortable date/time pattern | 2009-06-15T13:45:30 -> 2009-06-15T13:45:30 2009-06-15T13:45:30 -> 2009-06-15T13:45:30 |
t | Short time pattern | 2009-06-15T13:45:30 -> 1:45 PM en-US 2009-06-15T13:45:30 -> 13:45 hr-HR 2009-06-15T13:45:30 -> 01:45 ar-EG |
T | Long time pattern | 2009-06-15T13:45:30 -> 1:45:30 PM en-US 2009-06-15T13:45:30 -> 13:45:30 hr-HR 2009-06-15T13:45:30 -> 01:45:30 م ar-EG |
u | Universal sortable date/time pattern | 2009-06-15T13:45:30 -> 2009-06-15 20:45:30Z |
U | Universal full date/time pattern | 2009-06-15T13:45:30 -> Monday, June 15, 2009 8:45:30 PM en-US 2009-06-15T13:45:30 -> den 15 juni 2009 20:45:30 sv-SE 2009-06-15T13:45:30 -> Δευτέρα, 15 Ιουνίου 2009 8:45:30 μμ el-GR |
Y, y | Year month pattern | 2009-06-15T13:45:30 -> June, 2009 en-US 2009-06-15T13:45:30 -> juni 2009 da-DK 2009-06-15T13:45:30 -> Juni 2009 id-ID |
That is all there is to using .NET date format specifiers. Date Time Week will continue tomorrow when I will talk about more cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at [email protected], or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Dr Scripto
Scripter, PowerShell, vbScript, BAT, CMD
Follow Dr Scripto
devblogs.microsoft.com
PowerShell — Дата и Время — saw-friendship
DateTime: The truth is out there…
Так, у меня есть 30 дней для оплаты штрафа. А какое сегодня число? Ой, а месяц-то какой? Кажется февраль… А год не високосный ли?
Да, наплевать! Есть же (Get-Date).AddDays(30) !!
Далее небольшая история и много примеров работы с классом [DateTime], которые вам обязательно пригодятся, раз вы сюда попали
Когда я только начинал изучать PowerShell, я увидел много интересных и непонятных вещей, но именно класс [DateTime] был самым непонятным, поэтому я долго пытался обходить его стороной. Наверное, это связано с тем, что для написания PowerShell скриптов какое-то время совсем необязательно знать что такое методы и функции, но [DateTime] просто заставляет в это погрузиться и оказывается, все не так сложно…
Языки программирования, которые я поверхностно изучал в институте, вероятно, позволяли пользоваться какими-то методами, создавать классы и т.д., но, вероятно, для этого нужно было написать очень много строк кода, и я не представлял, что когда-нибудь я смогу создавать небольшие программы без всяких компиляторов, студий и т.д. так просто, что даже для простых задач, выполняемых мышкой, стало проще написать скрипт, чем действительно делать их мышкой.
Я думаю, что любую сущность надо прочувствовать. Я написал уже несколько десятков скриптов для ActiveDirectory, прежде чем смог сказать, что я знаю, что такое ActiveDirectory 🙂
В книгах и статьях можно найти разные объяснения про объекты, их свойства и методы. Что-то вроде следующего:
Есть дом — это объект, у него есть длина, ширина, высота — это свойства. У него есть и метод — звонок, нажми на звонок, и из дома вылетит…
Как-то не складно…
Так вот чтобы почувствовать что PowerShell — это ООП, почувствовать его мощь и попробовать понять что это такое и зачем это нужно в скриптовом языке, давайте обратимся за помощью к классу [DateTime]
В PowerShell есть много типов данных, проверить тип данных какого-то конкретного экземпляра можно с помощью метода GetType. Создадим переменную $Date и присвоим ей значение — текущую дату:
$Date = Get-Date
Убедимся что переменная $Date теперь представляет собой экземпляр класса [DateTime]
PS> $Date.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DateTime System.ValueType PS>
Свойства:
Что бы просмотреть свойства объекта, можно передать его по конвейеру в командлет select
PS> $Date | select * DisplayHint : DateTime DateTime : 17 июля 2017 г. 17:06:47 Date : 17.07.2017 0:00:00 Day : 17 DayOfWeek : Monday DayOfYear : 198 Hour : 17 Kind : Local Millisecond : 78 Minute : 6 Month : 7 Second : 47 Ticks : 636359080070781099 TimeOfDay : 17:06:47.0781099 Year : 2017 PS>
Теперь мы поняли, что то, что мы видим на выходе командлета Get-Date, это просто удобное представление времени, но на самом деле это не строка, а объект, у которого есть свойства и к этим свойствам можно обратиться через точку. Например:
PS> $Date.Date 17 июля 2017 г. 0:00:00 PS> $Date.DayOfWeek Monday PS> PS>
Методы:
$Date | Get-Member
С помощью Get-Member (чаще я использую алиас gm), мы видим методы, применяемые к классам. Метод — это функция, которая может принимать на вход аргументы. Если сравнить это со свойствами, которые показаны выше, то можно заметить что свойство DayOfWeek не может принимать никакие аргументы, они здесь не нужны, т.к. это свойство просто выводит день недели. Методы отличаются от свойств тем, что они выполняют какие-то действия.
В данном случае у нас класс [DateTime], посмотрим его методы через Get-Member (результат довольно большой, показывать не буду, выполняйте сами). Сейчас нам нужны только методы, поэтому уточним запрос:
$Date | Get-Member -MemberType Method
Теперь мы видим только методы. Выберем какой-нибудь из них, например AddDays.
Из названия метода AddDays понятно, что можно «добавить день».
Аргументы для методов передаются в скобках и называются страшным словом «перегрузка», но поскольку методы не имеют именованных параметров, важно соблюдать порядок, в котором аргументы передаются.
Итак мы решили воспользоваться методом AddDays, а когда смотрели Get-Member, то в Definition видели «double value» (число с плавающей запятой, см. типы данных). Теперь мы знаем что через точку можем обратиться к свойствам и методам, но методам можно передавать аргументы в скобках. Значит так и напишем: Экземпляр класса (объект), точка, метод, аргумент в скобках. Аргументом у нас будет число «2»,
Попробуем:
PS> $Date.AddDays(2) 19 июля 2017 г. 17:06:47 PS>
Теперь нецелое отрицательное
PS> $Date.AddDays(-1.5) 16 июля 2017 г. 5:06:47 PS>
Отлично, мы отняли полтора дня!
Это можно использовать и в командлетах:
PS# Get-EventLog -LogName Security -After (Get-Date).AddDays(-1) -Newest 3 Index Time EntryType Source InstanceID Message ----- ---- --------- ------ ---------- ------- 541 июл 17 18:05 SuccessA... Microsoft-Windows... 4801 Разблокирована рабочая станция.... 540 июл 17 17:28 SuccessA... Microsoft-Windows... 4800 Заблокирована рабочая станция.... 539 июл 17 16:12 SuccessA... Microsoft-Windows... 4801 Разблокирована рабочая станция.... PS#
PS# ls $env:USERPROFILE\Desktop | ? {$_.LastWriteTime -ge (Get-Date).AddDays(-1)} Каталог: C:\Users\User\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 17.07.2017 1:20 script2.1 -a---- 16.07.2017 23:24 3234 script1.ps1 -a---- 16.07.2017 23:16 1660 readme.txt PS#
Во многих командлетах на вход принимается именно дата, причем дата может быть указана и в виде текста (правда лучше так не делать).
Убедимся, напишем простую функцию «When», принимающую на вход один аргумент (именованный параметр «Date»):
PS> Function When { >> param( >> [Parameter(Mandatory=$true)][DateTime]$Date >> ) >> >> $Date >> } PS> PS> PS> PS> PS> When -Date (Get-Date).AddDays(-1) 16 июля 2017 г. 18:56:34 PS> PS> PS> When -Date '06.16.2017 18:56:34' 16 июня 2017 г. 18:56:34 PS>
Несколько примеров создания объекта [DateTime]
В этом примере в целом все нормально, но если не указать какой-либо из параметров, то аргумент для параметра будет взят из текущей даты
Get-Date -Year 2017 -Month 12 -Day 06 -Hour 18 -Minute 55 -Second 0
Или тоже самое, но через сплаттинг
$param = @{ 'Year'=2017; 'Month'=12; 'Day'=6; 'Hour'=18; 'Minute'=55; 'Second'=0 } Get-Date @param
Через стандартное создание объекта с перегрузкой, выше я говорил, что в перегрузке методов важен порядок, поэтому если что-то упустить, то создание объекта завершится ошибкой, тем не менее, это хороший способ
New-Object DateTime (2017, 12, 06, 18, 55, 00)
Или так
[DateTime]::new(2017, 12, 06, 18, 55, 00)
Преобразование типа из string в datetime, (плохой метод)
[DateTime]'2017.12.06 18:55:00'
Почему? Да потому что легко допустить ошибку, стоит нам написать дату так, как мы видим ее в пуске Windows, если язык системы русский, то мы получим неправильное распознавание. Простой пример:
PS> [datetime]’12.07.2017 14:55:00′
7 декабря 2017 г. 14:55:00
PS>
Мы получили 7-е декабря! Это не по-русски 🙂 Поэтому предлагаю самый правильный вариант получения даты из string, он больше всего подходит для парсинга логов, потому что он позволяет не просто отдать строку на неконтролируемое преобразование, а задать шаблон по которому преобразование производить
[DateTime]::ParseExact('2017.12.06 18:55:00','yyyy.MM.dd HH:mm:ss',$null)
В русских форматах нам достаточно двух аргументов, третий тоже необходимо указать, но тут он равен $null (если работать в одной локальной системе), но если у нас разные системы на разных языках, мы можем заставить PowerShell выводить или принимать дату на любом языке. Нам придется чуть-чуть углубиться в еще один класс [System.Globalization.CultureInfo] или сокращенно [CultureInfo]
Третий аргумент отвечает за языковые особенности формата дат, а его тип «CultureInfo»
Текущая культура
PS> [CultureInfo]::CurrentCulture LCID Name DisplayName ---- ---- ----------- 1049 ru-RU Русский (Россия) PS>
Американская культура
PS> [CultureInfo]::GetCultureInfo('en-US') LCID Name DisplayName ---- ---- ----------- 1033 en-US Английский (США) PS>
Выведем дату в американском формате
PS> (Get-Date).ToString([CultureInfo]::GetCultureInfo('en-US')) 7/18/2017 3:27:35 PM PS>
А теперь преобразуем строку с полученной выше датой обратно в объект
PS> $str = (Get-Date).ToString([cultureinfo]::GetCultureInfo('en-US')) PS> PS> $str 7/18/2017 3:30:40 PM PS> PS> PS> [datetime]::ParseExact($str, 'M/d/yyyy h:m:s tt', [cultureinfo]::GetCultureInfo('en-US')) 18 июля 2017 г. 15:30:40 PS>
Сравнение:
В скриптах нам часто требуется сравнивать две даты между собой или сортировать по дате. PowerShell позволяет сравнивать даты как будто это числа (хотя так оно, конечно, и есть).
Обращаю внимание на то, что заключаю командлет в скобки для того, чтобы как в математике, сначала выполнять операцию в скобках, ведь очевидно, что нельзя один командлет вычесть из другого, но их результаты — это уже конкретные значения, над которыми можно проводить операции вычитания, сложения и т.д..
Убедимся:
PS> (Get-Date) -lt (Get-Date).AddSeconds(1) True PS> PS> PS> (Get-Date) -gt (Get-Date).AddSeconds(1) False PS> PS>
Сортировка:
PS> 1..3 | % {[DateTime]::new(2017, 12, 06, 18, 55, $_)} | Sort-Object -Descending 6 декабря 2017 г. 18:55:03 6 декабря 2017 г. 18:55:02 6 декабря 2017 г. 18:55:01 PS>
Вычитание дат:
В жизни мы иногда задаемся вопросом: «Сколько же с тех пор времени прошло?», и даже не верится, что в PowerShell такую операцию можно совершить с помощью знака минус, но как бы это ни казалось чудом, это возможно 🙂
Результатом вычитания двух дат будет объект класса [TimeSpan] (следует понимать как временной интервал)
PS> (Get-Date) - (Get-Date).AddDays(-3) Days : 3 Hours : 0 Minutes : 0 Seconds : 0 Milliseconds : 0 Ticks : 2592000000000 TotalDays : 3 TotalHours : 72 TotalMinutes : 4320 TotalSeconds : 259200 TotalMilliseconds : 259200000 PS>
Кстати убедимся, что это действительно [TimeSpan]
PS> $TimeSpan = (Get-Date) - (Get-Date).AddDays(-3) PS> $TimeSpan.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True TimeSpan System.ValueType PS>
А теперь самое интересное: две даты конечно сложить нельзя, но к дате можно прибавить TimeSpan
PS> (Get-Date) + $TimeSpan 21 июля 2017 г. 1:15:33 PS>
Причем к TimeSpan нельзя прибавить дату, это не совсем математика, от перестановки слагаемых вы получите ошибку. Это вызвано невозможностью преобразования типа данных.
Создать объект класса TimeSpan можно несколькими способами, вот 3 варианта на выбор:
[TimeSpan]::new(0,1,0,0,0)
New-Object TimeSpan (0,1,0,0,0)
[TimeSpan]::FromHours(1)
Как видим, результат один и тот же:
PS> $Date + [TimeSpan]::new(0,1,0,0,0) 17 июля 2017 г. 18:06:47 PS> PS> $Date + (New-Object TimeSpan (0,1,0,0,0) ) 17 июля 2017 г. 18:06:47 PS> PS> $Date + [TimeSpan]::FromHours(1) 17 июля 2017 г. 18:06:47 PS>
Форматирование
Нам потребуется метод ToString
Сначала несколько слов в продолжение о TimeSpan, по умолчанию TimeSpan форматирует вывод следующим образом:
PS> $TimeSpan = [TimeSpan]::new(0,3,0,0,0) PS> $TimeSpan.ToString() 03:00:00 PS> PS> PS> $TimeSpan = [TimeSpan]::new(1,3,0,0,0) PS> $TimeSpan.ToString() 1.03:00:00 PS>
Видим неприятный момент, если TimeSpan меньше одного дня, то день вообще не попадает в вывод, у нас есть возможность указать свой формат, но лучше заранее знать разрядность количества дней. Для этого мы должны передать методу ToString аргумент в виде строки (примеры тут):
PS> $TimeSpan.ToString('dd\.hh\:mm\:ss') 01.03:00:00 PS> PS> $TimeSpan.ToString('ddd\.hh\:mm\:ss') 001.03:00:00 PS>
Можно вставлять любые символы, но их обязательно нужно экранировать с помощью «\» (backslash)
PS> $TimeSpan.ToString('\d\:ddd\.\h\:hh\.\m\:mm\.\s\:ss') d:001.h:03.m:00.s:00 PS> PS>
Вернемся к DateTime, мы уже видели пример работы метода ToString, где аргументом у нас служил объект CultureInfo, но надо сказать, что никто не загоняет вас в рамки, аргументом может служить и строка.
Пожалуйста:
PS> (Get-Date).ToString('ddd, dd.MM.yyyy') Вт, 18.07.2017 PS> PS> (Get-Date).ToString('ddd, dd.MM.yyyy', [cultureinfo]::GetCultureInfo('en-US')) Tue, 18.07.2017 PS>
Или так:
PS> (Get-Date).ToString('hh:mm, ddd, dd MMM yyyy') 03:46, Вт, 18 июл 2017 PS> PS> PS> (Get-Date).ToString('hh:mm tt, ddd, dd MMM yyyy', [cultureinfo]::GetCultureInfo('en-US')) 03:46 PM, Tue, 18 Jul 2017 PS>
На последок бонус)))
Метод определения дней в месяце и проверки високосного года
PS> [DateTime]::DaysInMonth(2017,07) 31 PS> PS> [DateTime]::IsLeapYear(2016) True PS>
На этом все. Этой темы мы еще будем касаться, а пока можете попробовать придумать как рассчитать ваш возраст. В одной из следующих статей я расскажу вам о том, как решал ее я.
# ——————-
Статья написана после анализа интересов людей, пытающихся найти помощь по PowerShell в интернете. Больше всего кликов было на один из моих первых постов, который представлял собой маленький черновик по [DateTime] с примерами и особо без объяснений 🙂
Понравилось это:
Нравится Загрузка…
sawfriendship.wordpress.com
Конвертирование текста в формат DateTime с помощью PowerShell
Для представления даты и времени в 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)
Вот как то так 🙂
windowsnotes.ru