在 Powershell 中获取给定日期的 ISO 8601 年度周数
Get the ISO 8601 Week of Year of a given date in Powershell
正在搜索如何获得 ISO 8601 Week of Year in PowerShell, I've stumbled upon this question for C#。
尽量不要用 PowerShell 代码来解决这个问题,下面是我的 Powershell 移植。 (基于answer by user6887101)
我会暂时搁置这个 'not accepted' 以防有人想出更好的解决方案。
如user6887101 and explained in detail here所述,伪算法为:
ISO 8601 周从 星期一 开始,到 星期日.
结束
- 对于任何给定日期,找到与给定日期同一周的星期四
日期。例如。:
- 如果原始日期是
Sunday, January 1st XXXX
找到 Thursday, December 29th XXXX-1
- 如果原始日期是
Monday, December 31st XXXX
找到 Thursday, January 3rd XXXX+1
Year of the ISO 8601 Week
是包含 Thursday found in step 1
的那个(例如:XXXX-1
或 XXXX+1
)
ISO 8601 Week number
是 year from step 2
中的 number of Thursdays
(直到并包括找到的 Thursday 本身)
function Get-ISO8601Week (){
# Adapted from
[CmdletBinding()]
param(
[Parameter(
ValueFromPipeline = $true,
ValueFromPipelinebyPropertyName = $true
)] [datetime] $DateTime
)
process {
foreach ($_DateTime in $DateTime) {
$_ResultObject = [pscustomobject] @{
Year = $null
WeekNumber = $null
WeekString = $null
DateString = $_DateTime.ToString('yyyy-MM-dd dddd')
}
$_DayOfWeek = $_DateTime.DayOfWeek.value__
# In the underlying object, Sunday is always 0 (Monday = 1, ..., Saturday = 6) irrespective of the FirstDayOfWeek settings (Sunday/Monday)
# Since ISO 8601 week date (https://en.wikipedia.org/wiki/ISO_week_date) is Monday-based, flipping Sunday to 7 and switching to one-based numbering.
if ($_DayOfWeek -eq 0) {
$_DayOfWeek = 7
}
# Find the Thursday from this week:
# E.g.: If original date is a Sunday, January 1st , will find Thursday, December 29th from the previous year.
# E.g.: If original date is a Monday, December 31st , will find Thursday, January 3rd from the next year.
$_DateTime = $_DateTime.AddDays((4 - $_DayOfWeek))
# The above Thursday it's the Nth Thursday from it's own year, wich is also the ISO 8601 Week Number
$_ResultObject.WeekNumber = [math]::Ceiling($_DateTime.DayOfYear / 7)
$_ResultObject.Year = $_DateTime.Year
# The format requires the ISO week-numbering year and numbers are zero-left-padded (https://en.wikipedia.org/wiki/ISO_8601#General_principles)
# It's also easier to debug this way :)
$_ResultObject.WeekString = "$($_DateTime.Year)-W$("$($_ResultObject.WeekNumber)".PadLeft(2, '0'))"
Write-Output $_ResultObject
}
}
}
快速测试:
PS C:\> Get-Date | Get-ISO8601Week
Year WeekNumber WeekString DateString
---- ---------- ---------- ----------
2017 41 2017-W41 2017-10-11 Wednesday
在广泛的输入范围内测试正确的结果:
#<# Test Get-ISO8601Week (You can manually check accuracy @ https://planetcalc.com/1252/)
# Tested on $PSVersionTable.PSVersion :
# 5.1.15063.502
"Week starts on: $([System.Globalization.DateTimeFormatInfo]::CurrentInfo.FirstDayOfWeek)"
# Test dates from 2000-01-01 (730119) to 2020-12-31 (737789)
# To get the 'serial day number' for a given date, use:
# (Get-Date -Date '2020-12-31').Ticks / [timespan]::TicksPerDay
$WeekOfYearObjectGroupList = 730119..737789 | ForEach-Object -Process {[datetime]::new(($_ * [timespan]::TicksPerDay))} | Get-ISO8601Week | Group-Object -Property 'Year'
'============================================================='
foreach ($WeekOfYearObjectGroup in $WeekOfYearObjectGroupList) {
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -lt 1 } | Format-Table -AutoSize
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -in 1..2 } | Format-Table -AutoSize
'...........'
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -in 52..53 } | Format-Table -AutoSize
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -gt 53 } | Format-Table -AutoSize
'============================================================='
}
#>
'tricky' 日期样本@MSDN
您可以手动检查准确性@ https://planetcalc.com/1252/
<# Sample of 'tricky' dates referenced @ https://blogs.msdn.microsoft.com/shawnste/2006/01/24/iso-8601-week-of-year-format-in-microsoft-net/
...........
2004 52 2004-W52 2004-12-26 Sunday
2004 53 2004-W53 2004-12-27 Monday
2004 53 2004-W53 2004-12-28 Tuesday
2004 53 2004-W53 2004-12-29 Wednesday
2004 53 2004-W53 2004-12-30 Thursday
2004 53 2004-W53 2004-12-31 Friday
2004 53 2004-W53 2005-01-01 Saturday
2004 53 2004-W53 2005-01-02 Sunday
=============================================================
2005 1 2005-W01 2005-01-03 Monday
2005 1 2005-W01 2005-01-04 Tuesday
2005 1 2005-W01 2005-01-05 Wednesday
2005 1 2005-W01 2005-01-06 Thursday
2005 1 2005-W01 2005-01-07 Friday
2005 1 2005-W01 2005-01-08 Saturday
2005 1 2005-W01 2005-01-09 Sunday
2005 2 2005-W02 2005-01-10 Monday
...........
#>
聚会有点晚了,但是...只是想在这里留下这个答案,因为这个问题是我在寻找解决方案时偶然发现的第一个问题。有一个更简单的方法:
get-date -UFormat %V
或
"{0:d1}" -f ($(Get-Culture).Calendar.GetWeekOfYear((Get-Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday))
取决于您是否需要 ISO8601。
$checkdate = Get-Date -date "2007-12-31"
$dow=[int]($checkdate).dayofweek
# if the day of week is before Thurs (Mon-Wed) add 3 since Thursday is the critical
# day for determining when the ISO week starts.
if ($dow -match "[1-3]") {$checkdate.addDays(3)}
# Return the ISO week number
$(Get-Culture).Calendar.GetWeekOfYear(($checkdate),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
对于纯 Powershell:
Culture 和 UICulture 有问题
要以文化语言打印一周的第一天:
(Get-Culture).DateTimeFormat.DayNames[(Get-Culture).DateTimeFormat.FirstDayOfWeek.value__]
maandag (which is My language AND My starting weekday
(Get-uiCulture).DateTimeFormat.DayNames[(Get-Culture).DateTimeFormat.FirstDayOfWeek.value__]
Monday (which is NOT My language BUT is My starting weekday
(Get-uiCulture).DateTimeFormat.DayNames[(Get-uiCulture).DateTimeFormat.FirstDayOfWeek.value__]
Sunday (which is NOT My language AND NOT My starting weekday
(Get-Culture).DateTimeFormat.DayNames[(Get-uiCulture).DateTimeFormat.FirstDayOfWeek.value__]
zondag (which is My language AND NOT My starting weekday
还有周数不符合 ISO8601 标准的问题。
日期 2012-12-31 应该是第 1 周,但它给出了 53。
所以你必须实施某种解决方案。
(Get-Culture).Calendar.GetWeekOfYear((Get-Date).AddDays(3*([int](Get-Date).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
用于测试:
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2013-01-01')).AddDays(3*([int](Get-Date('2013-01-01')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2012-12-31')).AddDays(3*([int](Get-Date('2012-12-31')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2012-12-30')).AddDays(3*([int](Get-Date('2012-12-30')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
这些应该给出 1,1,52(正确)而不是 1,53,52(不正确)。
或者(UICulture相关版本)
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date).AddDays(3*([int](Get-Date).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
用于测试:
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2013-01-01')).AddDays(3*([int](Get-Date('2013-01-01')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-31')).AddDays(3*([int](Get-Date('2012-12-31')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-30')).AddDays(3*([int](Get-Date('2012-12-30')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-29')).AddDays(3*([int](Get-Date('2012-12-29')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
这些应该给出 1,1,1,52(正确)而不是 1,53,53,52(不正确)。
因为开始工作日是星期日。
您可以通过将 3* 替换为 0* 来测试不正确的结果。
把它变成一个函数,你可以不给它参数一个日期或一个字符串:
function Get-ISO8601Week {
Param(
$getISO8601Week = $(Get-Date)
)
If ($getISO8601Week.GetType() -eq [string]){
$getISO8601Week = (Get-Date($getISO8601Week))
}
$getCulture = Get-Culture
($getCulture).Calendar.GetWeekOfYear(
$getISO8601Week.AddDays(
3*([int]$getISO8601Week.DayOfWeek -in (0,1,2))
), ($getCulture.DateTimeFormat.CalendarWeekRule
), ($getCulture.DateTimeFormat.FirstDayOfWeek
)
)
}
Get-ISO8601Week $(Get-Date('2012-12-31'))
1
Get-ISO8601Week (Get-Date('2012-12-31'))
1
Get-ISO8601Week '2012-12-31'
1
当我写这篇文章时:
Get-ISO8601Week
4
确定(荷兰)文化和 UICulture 的最终抽签。
我通过创建 WeekRuleDay 解决了它:
function Get-ISO8601Week {
Param(
[datetime]$DT = (Get-Date)
)
<#
First create an integer(0/1) from the boolean,
"Is the integer DayOfWeek value greater than zero?".
Then Multiply it with 4 or 6 (weekrule = 0 or 2) minus the integer DayOfWeek value.
This turns every day (except Sunday) into Thursday.
Then return the ISO8601 WeekNumber.
#>
$Cult = Get-Culture; $DT = Get-Date($DT)
$WeekRule = $Cult.DateTimeFormat.CalendarWeekRule.value__
$FirstDayOfWeek = $Cult.DateTimeFormat.FirstDayOfWeek.value__
$WeekRuleDay = [int]($DT.DayOfWeek.Value__ -ge $FirstDayOfWeek ) * ( (6 - $WeekRule) - $DT.DayOfWeek.Value__ )
$Cult.Calendar.GetWeekOfYear(($DT).AddDays($WeekRuleDay), $WeekRule, $FirstDayOfWeek)
}
function Get-UiISO8601Week {
Param(
[datetime]$DT = (Get-Date)
)
<#
First create an integer(0/1) from the boolean,
"Is the integer DayOfWeek value greater than zero?".
Then Multiply it with 4 or 6 (weekrule = 0 or 2) minus the integer DayOfWeek value.
This turns every day (except Sunday) into Thursday.
Then return the ISO8601 WeekNumber.
#>
$Cult = Get-UICulture; $DT = Get-Date($DT)
$WeekRule = $Cult.DateTimeFormat.CalendarWeekRule.value__
$FirstDayOfWeek = $Cult.DateTimeFormat.FirstDayOfWeek.value__
$ThursSunDay = [int]($DT.DayOfWeek.Value__ -ge $FirstDayOfWeek ) * ( (6 - $WeekRule) - $DT.DayOfWeek.Value__ )
$Cult.Calendar.GetWeekOfYear(($DT).AddDays($ThursSunDay), $WeekRule, $FirstDayOfWeek)
}
Write-Host "UICulture: " -NoNewline
(20..31).ForEach( { Get-UiISO8601Week("2012-12-$($_)") }) + ((1..7).ForEach( { Get-UiISO8601Week("2013-1-$($_)") })) -join ', '
Write-Host " Culture: " -NoNewline
(20..31).ForEach( { Get-ISO8601Week("2012-12-$($_)") }) + ((1..7).ForEach( { Get-ISO8601Week("2013-1-$($_)") })) -join ', '
这可以作为错误修复!
我想我找到了一个非常可靠的实现。
#ISO week
$date = [DateTime] '2014-12-29'
(Get-Culture).Calendar.GetWeekOfYear(($date).AddDays(-[Int] (($date).AddDays(-1)).DayOfWeek+3), 2, 1)
#ISO year
(Get-Culture).Calendar.GetYear(($date).AddDays(-[Int] (($date).AddDays(-1)).DayOfWeek+3))
这会计算一周中的星期四。
其他解决方案会错误地计算给定日期的第 53 周。
正在搜索如何获得 ISO 8601 Week of Year in PowerShell, I've stumbled upon this question for C#。
尽量不要用 PowerShell 代码来解决这个问题,下面是我的 Powershell 移植。 (基于answer by user6887101)
我会暂时搁置这个 'not accepted' 以防有人想出更好的解决方案。
如user6887101 and explained in detail here所述,伪算法为:
ISO 8601 周从 星期一 开始,到 星期日.
结束- 对于任何给定日期,找到与给定日期同一周的星期四
日期。例如。:
- 如果原始日期是
Sunday, January 1st XXXX
找到Thursday, December 29th XXXX-1
- 如果原始日期是
Monday, December 31st XXXX
找到Thursday, January 3rd XXXX+1
- 如果原始日期是
Year of the ISO 8601 Week
是包含Thursday found in step 1
的那个(例如:XXXX-1
或XXXX+1
)ISO 8601 Week number
是year from step 2
中的number of Thursdays
(直到并包括找到的 Thursday 本身)
function Get-ISO8601Week (){
# Adapted from
[CmdletBinding()]
param(
[Parameter(
ValueFromPipeline = $true,
ValueFromPipelinebyPropertyName = $true
)] [datetime] $DateTime
)
process {
foreach ($_DateTime in $DateTime) {
$_ResultObject = [pscustomobject] @{
Year = $null
WeekNumber = $null
WeekString = $null
DateString = $_DateTime.ToString('yyyy-MM-dd dddd')
}
$_DayOfWeek = $_DateTime.DayOfWeek.value__
# In the underlying object, Sunday is always 0 (Monday = 1, ..., Saturday = 6) irrespective of the FirstDayOfWeek settings (Sunday/Monday)
# Since ISO 8601 week date (https://en.wikipedia.org/wiki/ISO_week_date) is Monday-based, flipping Sunday to 7 and switching to one-based numbering.
if ($_DayOfWeek -eq 0) {
$_DayOfWeek = 7
}
# Find the Thursday from this week:
# E.g.: If original date is a Sunday, January 1st , will find Thursday, December 29th from the previous year.
# E.g.: If original date is a Monday, December 31st , will find Thursday, January 3rd from the next year.
$_DateTime = $_DateTime.AddDays((4 - $_DayOfWeek))
# The above Thursday it's the Nth Thursday from it's own year, wich is also the ISO 8601 Week Number
$_ResultObject.WeekNumber = [math]::Ceiling($_DateTime.DayOfYear / 7)
$_ResultObject.Year = $_DateTime.Year
# The format requires the ISO week-numbering year and numbers are zero-left-padded (https://en.wikipedia.org/wiki/ISO_8601#General_principles)
# It's also easier to debug this way :)
$_ResultObject.WeekString = "$($_DateTime.Year)-W$("$($_ResultObject.WeekNumber)".PadLeft(2, '0'))"
Write-Output $_ResultObject
}
}
}
快速测试:
PS C:\> Get-Date | Get-ISO8601Week
Year WeekNumber WeekString DateString
---- ---------- ---------- ----------
2017 41 2017-W41 2017-10-11 Wednesday
在广泛的输入范围内测试正确的结果:
#<# Test Get-ISO8601Week (You can manually check accuracy @ https://planetcalc.com/1252/)
# Tested on $PSVersionTable.PSVersion :
# 5.1.15063.502
"Week starts on: $([System.Globalization.DateTimeFormatInfo]::CurrentInfo.FirstDayOfWeek)"
# Test dates from 2000-01-01 (730119) to 2020-12-31 (737789)
# To get the 'serial day number' for a given date, use:
# (Get-Date -Date '2020-12-31').Ticks / [timespan]::TicksPerDay
$WeekOfYearObjectGroupList = 730119..737789 | ForEach-Object -Process {[datetime]::new(($_ * [timespan]::TicksPerDay))} | Get-ISO8601Week | Group-Object -Property 'Year'
'============================================================='
foreach ($WeekOfYearObjectGroup in $WeekOfYearObjectGroupList) {
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -lt 1 } | Format-Table -AutoSize
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -in 1..2 } | Format-Table -AutoSize
'...........'
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -in 52..53 } | Format-Table -AutoSize
$WeekOfYearObjectGroup.Group | Where-Object {$_.WeekNumber -gt 53 } | Format-Table -AutoSize
'============================================================='
}
#>
'tricky' 日期样本@MSDN
您可以手动检查准确性@ https://planetcalc.com/1252/
<# Sample of 'tricky' dates referenced @ https://blogs.msdn.microsoft.com/shawnste/2006/01/24/iso-8601-week-of-year-format-in-microsoft-net/
...........
2004 52 2004-W52 2004-12-26 Sunday
2004 53 2004-W53 2004-12-27 Monday
2004 53 2004-W53 2004-12-28 Tuesday
2004 53 2004-W53 2004-12-29 Wednesday
2004 53 2004-W53 2004-12-30 Thursday
2004 53 2004-W53 2004-12-31 Friday
2004 53 2004-W53 2005-01-01 Saturday
2004 53 2004-W53 2005-01-02 Sunday
=============================================================
2005 1 2005-W01 2005-01-03 Monday
2005 1 2005-W01 2005-01-04 Tuesday
2005 1 2005-W01 2005-01-05 Wednesday
2005 1 2005-W01 2005-01-06 Thursday
2005 1 2005-W01 2005-01-07 Friday
2005 1 2005-W01 2005-01-08 Saturday
2005 1 2005-W01 2005-01-09 Sunday
2005 2 2005-W02 2005-01-10 Monday
...........
#>
聚会有点晚了,但是...只是想在这里留下这个答案,因为这个问题是我在寻找解决方案时偶然发现的第一个问题。有一个更简单的方法:
get-date -UFormat %V
或
"{0:d1}" -f ($(Get-Culture).Calendar.GetWeekOfYear((Get-Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday))
取决于您是否需要 ISO8601。
$checkdate = Get-Date -date "2007-12-31"
$dow=[int]($checkdate).dayofweek
# if the day of week is before Thurs (Mon-Wed) add 3 since Thursday is the critical
# day for determining when the ISO week starts.
if ($dow -match "[1-3]") {$checkdate.addDays(3)}
# Return the ISO week number
$(Get-Culture).Calendar.GetWeekOfYear(($checkdate),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
对于纯 Powershell: Culture 和 UICulture 有问题 要以文化语言打印一周的第一天:
(Get-Culture).DateTimeFormat.DayNames[(Get-Culture).DateTimeFormat.FirstDayOfWeek.value__]
maandag (which is My language AND My starting weekday
(Get-uiCulture).DateTimeFormat.DayNames[(Get-Culture).DateTimeFormat.FirstDayOfWeek.value__]
Monday (which is NOT My language BUT is My starting weekday
(Get-uiCulture).DateTimeFormat.DayNames[(Get-uiCulture).DateTimeFormat.FirstDayOfWeek.value__]
Sunday (which is NOT My language AND NOT My starting weekday
(Get-Culture).DateTimeFormat.DayNames[(Get-uiCulture).DateTimeFormat.FirstDayOfWeek.value__]
zondag (which is My language AND NOT My starting weekday
还有周数不符合 ISO8601 标准的问题。 日期 2012-12-31 应该是第 1 周,但它给出了 53。 所以你必须实施某种解决方案。
(Get-Culture).Calendar.GetWeekOfYear((Get-Date).AddDays(3*([int](Get-Date).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
用于测试:
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2013-01-01')).AddDays(3*([int](Get-Date('2013-01-01')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2012-12-31')).AddDays(3*([int](Get-Date('2012-12-31')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
(Get-Culture).Calendar.GetWeekOfYear((Get-Date('2012-12-30')).AddDays(3*([int](Get-Date('2012-12-30')).DayOfWeek -in (1,2,3))), ((Get-Culture).DateTimeFormat.CalendarWeekRule), ((Get-Culture).DateTimeFormat.FirstDayOfWeek))
这些应该给出 1,1,52(正确)而不是 1,53,52(不正确)。 或者(UICulture相关版本)
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date).AddDays(3*([int](Get-Date).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
用于测试:
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2013-01-01')).AddDays(3*([int](Get-Date('2013-01-01')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-31')).AddDays(3*([int](Get-Date('2012-12-31')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-30')).AddDays(3*([int](Get-Date('2012-12-30')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
(Get-UICulture).Calendar.GetWeekOfYear((Get-Date('2012-12-29')).AddDays(3*([int](Get-Date('2012-12-29')).DayOfWeek -in (0,1,2))), ((Get-UICulture).DateTimeFormat.CalendarWeekRule), ((Get-UICulture).DateTimeFormat.FirstDayOfWeek))
这些应该给出 1,1,1,52(正确)而不是 1,53,53,52(不正确)。 因为开始工作日是星期日。
您可以通过将 3* 替换为 0* 来测试不正确的结果。
把它变成一个函数,你可以不给它参数一个日期或一个字符串:
function Get-ISO8601Week {
Param(
$getISO8601Week = $(Get-Date)
)
If ($getISO8601Week.GetType() -eq [string]){
$getISO8601Week = (Get-Date($getISO8601Week))
}
$getCulture = Get-Culture
($getCulture).Calendar.GetWeekOfYear(
$getISO8601Week.AddDays(
3*([int]$getISO8601Week.DayOfWeek -in (0,1,2))
), ($getCulture.DateTimeFormat.CalendarWeekRule
), ($getCulture.DateTimeFormat.FirstDayOfWeek
)
)
}
Get-ISO8601Week $(Get-Date('2012-12-31'))
1
Get-ISO8601Week (Get-Date('2012-12-31'))
1
Get-ISO8601Week '2012-12-31'
1
当我写这篇文章时:
Get-ISO8601Week
4
确定(荷兰)文化和 UICulture 的最终抽签。
我通过创建 WeekRuleDay 解决了它:
function Get-ISO8601Week {
Param(
[datetime]$DT = (Get-Date)
)
<#
First create an integer(0/1) from the boolean,
"Is the integer DayOfWeek value greater than zero?".
Then Multiply it with 4 or 6 (weekrule = 0 or 2) minus the integer DayOfWeek value.
This turns every day (except Sunday) into Thursday.
Then return the ISO8601 WeekNumber.
#>
$Cult = Get-Culture; $DT = Get-Date($DT)
$WeekRule = $Cult.DateTimeFormat.CalendarWeekRule.value__
$FirstDayOfWeek = $Cult.DateTimeFormat.FirstDayOfWeek.value__
$WeekRuleDay = [int]($DT.DayOfWeek.Value__ -ge $FirstDayOfWeek ) * ( (6 - $WeekRule) - $DT.DayOfWeek.Value__ )
$Cult.Calendar.GetWeekOfYear(($DT).AddDays($WeekRuleDay), $WeekRule, $FirstDayOfWeek)
}
function Get-UiISO8601Week {
Param(
[datetime]$DT = (Get-Date)
)
<#
First create an integer(0/1) from the boolean,
"Is the integer DayOfWeek value greater than zero?".
Then Multiply it with 4 or 6 (weekrule = 0 or 2) minus the integer DayOfWeek value.
This turns every day (except Sunday) into Thursday.
Then return the ISO8601 WeekNumber.
#>
$Cult = Get-UICulture; $DT = Get-Date($DT)
$WeekRule = $Cult.DateTimeFormat.CalendarWeekRule.value__
$FirstDayOfWeek = $Cult.DateTimeFormat.FirstDayOfWeek.value__
$ThursSunDay = [int]($DT.DayOfWeek.Value__ -ge $FirstDayOfWeek ) * ( (6 - $WeekRule) - $DT.DayOfWeek.Value__ )
$Cult.Calendar.GetWeekOfYear(($DT).AddDays($ThursSunDay), $WeekRule, $FirstDayOfWeek)
}
Write-Host "UICulture: " -NoNewline
(20..31).ForEach( { Get-UiISO8601Week("2012-12-$($_)") }) + ((1..7).ForEach( { Get-UiISO8601Week("2013-1-$($_)") })) -join ', '
Write-Host " Culture: " -NoNewline
(20..31).ForEach( { Get-ISO8601Week("2012-12-$($_)") }) + ((1..7).ForEach( { Get-ISO8601Week("2013-1-$($_)") })) -join ', '
这可以作为错误修复!
我想我找到了一个非常可靠的实现。
#ISO week
$date = [DateTime] '2014-12-29'
(Get-Culture).Calendar.GetWeekOfYear(($date).AddDays(-[Int] (($date).AddDays(-1)).DayOfWeek+3), 2, 1)
#ISO year
(Get-Culture).Calendar.GetYear(($date).AddDays(-[Int] (($date).AddDays(-1)).DayOfWeek+3))
这会计算一周中的星期四。 其他解决方案会错误地计算给定日期的第 53 周。