О разных тиках замолвите слово или как не получить ошибку в Powershell при работе с Get-Date

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Доброго дня, любители Powershell.

Я люблю его, и сегодня заметил одну странность, которая мотивировала к написанию данного поста. Думаю, вам тоже будет интересно. Дело о лишнем тике. Если интересно, добро пожаловать под кат:

В чем суть странности?

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

Вычислялось это одной строкой такого вида:

((Get-date -Day 1).AddMonths(1)-(get-date)).days-1

Что характерно ее вычисление может давать разные результаты:

Сначала я подумал, что с кодом что-то не то, или версией Powershell.

Проверил на нескольких машинках и понял, что ситуация воспроизводима.

Поэтому сел дебажить и писать функцию.

У меня получилось такое, в коде сразу идут комментарии:

Function Get-DaysToEndOfMonths([int]$Month=1)
    {If($Month -lt 1){[int]$Month = 1}
    $CurrentDate = get-date       #Получаем текущую дату
    $CurrentDay = $CurrentDate.day #И какой это день
    $FirstDayCurrentMonths = (Get-date -Day 1) #Первый день текущего месяца
   #$FirstDayNextMonths = $FirstDayCurrentMonths.AddMonths($Month) #Первый день искомого месяца
   #Ага, так можно сразу отнять один день, чтобы получить последний день до искомого месяца
    $LastDay = $FirstDayCurrentMonths.AddMonths($Month).AddDays(-1) #Последний день искомого месяца
    $DaysToEndOfMonths = $($LastDay - $CurrentDate).Days #Сколько дней до искомого месяца
    #Или через New-TimeSpan
    #$NewTimeSpan = New-TimeSpan -Start $CurrentDate -End $LastDay
    #$DaysToEndOfMonths = $NewTimeSpan.Days #Сколько дней
    Write-debug "$DaysToEndOfMonths days to the end of the next $Month month"
    }
Get-DaysToEndOfMonths(1)

Ну и после того как написал, сел еще подумать и пришел к такой строке:

[int]((((Get-Date -day 01).AddMonths(1)).AddDays(-1)).Day-(Get-date).Day) 

Она уже не давала ошибку, но может, так как:

Оказывается, что мы не учитываем час\минуты\секунды, а вернее тактовые тики процессора.
Заметим, что, Get-date выдаёт значение в миллисекундах.

Но если при выполнении вычислений первый и второй вызов Get-date пришёлся на один тик, то будут такие значения:

(Get-date -day 1).AddMonth(1) = 1.12.2019 15:33:00:500
Get-date = 1.11.2019 15:33:00:500

Вычтем и получим 30 00:00:00:000
Но если вызов второго Get-date выпадает на следующий тик, то его значение будет
=>
1.11.2019 15:33:00:501

И тогда мы получим значение в
29 23:59:59:999

Теперь, когда проблема найдена, мы можем сделать так:


#Число дней до конца месяца
((((Get-Date -day 01).AddMonths(1)).AddDays(-1))-(Get-date -Hour 0 -Minute 0 -Second 0 -Millisecond 0)).Days

И у нас всегда будет одинаковое значение.

Будьте внимательны и хороших выходных!
Источник: https://habr.com/ru/post/474204/


Интересные статьи

Интересные статьи

Много всякого сыпется в мой ящик, в том числе и от Битрикса (справедливости ради стоит отметить, что я когда-то регистрировался на их сайте). Но вот мне надоели эти письма и я решил отписатьс...
Артем Светлов aka trolleway — программист из NextGIS, а также любитель архитектуры и общественного транспорта. Он не только правит OpenStreetMap, но и каждый день работает с данными из него. По...
Работа с государственными заказчиками весьма специфична. Но многим нравится, вкусы у всех разные. Госкомпании зачастую имеют большой бюджет на закупку, который может обеспечить поставщика ...
На сегодняшний день у сервиса «Битрикс24» нет сотен гигабит трафика, нет огромного парка серверов (хотя и существующих, конечно, немало). Но для многих клиентов он является основным инструментом ...
Тема статьи навеяна результатами наблюдений за методикой создания шаблонов различными разработчиками, чьи проекты попадали мне на поддержку. Порой разобраться в, казалось бы, такой простой сущности ка...