Pet*_*ria 3 powershell datetime date iso8601
在搜索如何在 PowerShell 中获取ISO 8601 Week of Year时,我偶然发现了 C# 的这个问题。
尽量不要用 PowerShell 代码来解决这个问题,下面是我的 Powershell 端口。(基于user6887101的回答)
如果有人想出更好的解决方案,我会将这个“不接受”保留一段时间。
正如user6887101所提到并在此处详细解释的,伪算法是:
与ISO 8601星期开始的星期一和结束与周日。
Sunday, January 1st XXXX找到Thursday, December 29th XXXX-1Monday, December 31st XXXX找到Thursday, January 3rd XXXX+1Year of the ISO 8601 Week是包含Thursday found in step 1(eg: XXXX-1or XXXX+1)ISO 8601 Week number是number of Thursdays在year from step 2(直至并包括发现周四本身)function Get-ISO8601Week (){
# Adapted from https://stackoverflow.com/a/43736741/444172
[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
}
}
}
Run Code Online (Sandbox Code Playgroud)
快速测试:
PS C:\> Get-Date | Get-ISO8601Week
Year WeekNumber WeekString DateString
---- ---------- ---------- ----------
2017 41 2017-W41 2017-10-11 Wednesday
Run Code Online (Sandbox Code Playgroud)
在广泛的输入范围内测试正确的结果:
#<# 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
'============================================================='
}
#>
Run Code Online (Sandbox Code Playgroud)
引用“棘手”日期@样本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
...........
#>
Run Code Online (Sandbox Code Playgroud)
聚会有点晚了,但是......只是想在这里留下这个答案,因为这个问题是我在寻找解决方案时偶然发现的第一件事。有一个更简单的方法:
get-date -UFormat %V
或者
"{0:d1}" -f ($(Get-Culture).Calendar.GetWeekOfYear((Get-Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday))
Run Code Online (Sandbox Code Playgroud)
取决于您是否想要 ISO8601。
| 归档时间: |
|
| 查看次数: |
3618 次 |
| 最近记录: |