PowerShell 如何处理一月份的 ((Get-Date).Month)-1?
How does PowerShell handle ((Get-Date).Month)-1 in January?
几个月前我写了一个 Powershell/Robocopy 备份脚本。它会为备份创建一个文件夹,其中包含备份的年份和月份(例如:2019 11)。这个月总是必须少一个,因为脚本 运行s 在每个新月的第一天。一切都一帆风顺,但我刚刚意识到我不太确定剧本在 1 月 1 日的表现如何。有没有人知道 1 月 1 日的输出是什么,我有没有办法对此进行测试以确认?
$month = (Get-Date -UFormat "%Y") + ' ' + ((((Get-Date).Month) - 1)).ToString()
# When run on November 1st, it creates a folder for the October backups called "2019 10".
# When run on December 1st, it creates a folder for the November backups called "2019 11".
在 1 月 1 日 运行 时,它将为 12 月备份的文件夹命名什么?会叫《2019 12》吗? “2019 00”?有没有一种方法可以让我轻松测试依赖于时间的行为,而无需手动调整我的 PC 的日历?
如果你能保证你总是运行这个月的第一天,那么你可以使用$folderName = ((Get-Date) - (New-TimeSpan -Days 1)).ToString("yyyy MM")
。参见 Microsoft Docs on New-TimeSpan
and this Whosebug question on formatting dates
编辑: 在这里得到更好的回应;不要使用上面的 New-Timespan
方法,而是将上面我建议的代码修改为
$foldername = (Get-Date).AddMonths(-1).ToString("yyyy MM")
这消除了支持代码在每月的第一天为 运行 的要求。
Get-Date
可选地接受要操作的日期(通过 -Date
或位置),默认为当前时间点。
此外,您可以使用-Day
修改目标日期的日期部分(以及-Month
和-Year
,类似);传递 -Day 1
returns 目标日期所在月份的第一天。
在结果日期上调用 .AddDays(-1)
然后保证在上个月(它 returns 上个月的最后一天)。
.ToString()
method of System.DateTime
allows you to perform custom string formatting of a date, using custom date and time format strings.
总而言之:
# PRODUCTION USE:
# The reference date - now.
$now = Get-Date
# OVERRIDE FOR TESTING:
# Set $now to an arbitrary date, 1 January 2020 in this case.
# Note: With this syntax, *month comes first*, irrespective or the current culture.
$now = [datetime] '1/1/2020'
# Get the first day of the month of the date in $now,
# subtract 1 day to get the last day of the previous month,
# then use .ToString() to produce the desired format.
(Get-Date $now -Day 1).AddDays(-1).ToString('yyyy MM')
以上结果:
2019 12
注意:PowerShell 的转换 例如 [datetime] '1/1/2020'
通常使用 invariant culture 来保证跨不同行为的稳定性文化;这种虚拟文化与美国英语文化相关联,并支持其以月为首的日期格式(例如,12/1/2020
指的是 2020 年 12 月 1 日,而不是 2020 年 1 月 12 日)。
令人惊讶的是,相比之下,当您将 参数 传递给 cmdlet 时,数据转换 文化敏感;也就是说,例如,在法国文化 (fr-FR
) 中,调用 Get-Date 12/1/2020
将导致 2020 年 1 月 12 日,而不是 2020 年 12 月 1 日,这就是它在美国英语中的 returns文化 (en-US
)).
在 this GitHub issue 中讨论了这种有问题的行为差异 - 但是,为了保持向后兼容性,该行为不太可能改变。
您可以像这样创建任意日期
$testdate = get-date -year 2020 -month 1 -day 1
然而,您的代码将生成“2020 0”作为输出。
你最好用这样的东西。您也不会在下个月的第一天绑定到 运行:
$month = $(get-date (get-date $testdate).AddMonths(-1) -format "yyyy MM")
几个月前我写了一个 Powershell/Robocopy 备份脚本。它会为备份创建一个文件夹,其中包含备份的年份和月份(例如:2019 11)。这个月总是必须少一个,因为脚本 运行s 在每个新月的第一天。一切都一帆风顺,但我刚刚意识到我不太确定剧本在 1 月 1 日的表现如何。有没有人知道 1 月 1 日的输出是什么,我有没有办法对此进行测试以确认?
$month = (Get-Date -UFormat "%Y") + ' ' + ((((Get-Date).Month) - 1)).ToString()
# When run on November 1st, it creates a folder for the October backups called "2019 10".
# When run on December 1st, it creates a folder for the November backups called "2019 11".
在 1 月 1 日 运行 时,它将为 12 月备份的文件夹命名什么?会叫《2019 12》吗? “2019 00”?有没有一种方法可以让我轻松测试依赖于时间的行为,而无需手动调整我的 PC 的日历?
如果你能保证你总是运行这个月的第一天,那么你可以使用$folderName = ((Get-Date) - (New-TimeSpan -Days 1)).ToString("yyyy MM")
。参见 Microsoft Docs on New-TimeSpan
and this Whosebug question on formatting dates
编辑:New-Timespan
方法,而是将上面我建议的代码修改为
$foldername = (Get-Date).AddMonths(-1).ToString("yyyy MM")
这消除了支持代码在每月的第一天为 运行 的要求。
Get-Date
可选地接受要操作的日期(通过 -Date
或位置),默认为当前时间点。
此外,您可以使用-Day
修改目标日期的日期部分(以及-Month
和-Year
,类似);传递 -Day 1
returns 目标日期所在月份的第一天。
在结果日期上调用 .AddDays(-1)
然后保证在上个月(它 returns 上个月的最后一天)。
.ToString()
method of System.DateTime
allows you to perform custom string formatting of a date, using custom date and time format strings.
总而言之:
# PRODUCTION USE:
# The reference date - now.
$now = Get-Date
# OVERRIDE FOR TESTING:
# Set $now to an arbitrary date, 1 January 2020 in this case.
# Note: With this syntax, *month comes first*, irrespective or the current culture.
$now = [datetime] '1/1/2020'
# Get the first day of the month of the date in $now,
# subtract 1 day to get the last day of the previous month,
# then use .ToString() to produce the desired format.
(Get-Date $now -Day 1).AddDays(-1).ToString('yyyy MM')
以上结果:
2019 12
注意:PowerShell 的转换 例如 [datetime] '1/1/2020'
通常使用 invariant culture 来保证跨不同行为的稳定性文化;这种虚拟文化与美国英语文化相关联,并支持其以月为首的日期格式(例如,12/1/2020
指的是 2020 年 12 月 1 日,而不是 2020 年 1 月 12 日)。
令人惊讶的是,相比之下,当您将 参数 传递给 cmdlet 时,数据转换 文化敏感;也就是说,例如,在法国文化 (fr-FR
) 中,调用 Get-Date 12/1/2020
将导致 2020 年 1 月 12 日,而不是 2020 年 12 月 1 日,这就是它在美国英语中的 returns文化 (en-US
)).
在 this GitHub issue 中讨论了这种有问题的行为差异 - 但是,为了保持向后兼容性,该行为不太可能改变。
您可以像这样创建任意日期
$testdate = get-date -year 2020 -month 1 -day 1
然而,您的代码将生成“2020 0”作为输出。 你最好用这样的东西。您也不会在下个月的第一天绑定到 运行:
$month = $(get-date (get-date $testdate).AddMonths(-1) -format "yyyy MM")