【问题标题】:How is first day of week determined in powershell?PowerShell中如何确定一周的第一天?
【发布时间】:2021-02-12 16:26:48
【问题描述】:

我有一个运行 powershell 脚本的计划任务,该脚本运行带有一些参数的可执行文件。其中一个参数是当前周数。

我在 powershell 中使用以下代码来检索周数:

get-date -uformat %V

这似乎返回了错误的周数

  • 2014-05-04(星期日),第 18 周返回(如预期)
  • 2014-05-05(星期一),第 18 周返回(预计 19 日)
  • 2014-05-06(星期二),返回第 19 周(如预期)

在我的注册表中,一周的第一天设置为星期一 (HKEY_CURRENT_USER->Control Panel->International->iFirstDayOfWeek = 0)

有谁知道 powershell 从哪里检索它的 firstDayOfWeek 设置?我应该(/可以)以其他方式在脚本中设置它吗?

我知道一种解决方法是使用 .AddDays(1),但我正在寻找更简洁的解决方案。

编辑: 好吧,这真的很奇怪,我收到不同年份的不同“一周的第一天”..

2012 - 星期六:

PS C:\Users\A730978F> get-date -date "2012-01-08" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-08 Sun Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-09" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-09 Mon Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-10" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-10 Tue Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-11" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-11 Wed Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-12" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-12 Thu Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-13" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-13 Fri Week: 2
PS C:\Users\A730978F> get-date -date "2012-01-14" -uFormat "%Y-%m-%d %a Week: %V"
2012-01-14 Sat Week: 3

2013 - 星期一:

PS C:\Users\A730978F> get-date -date "2013-01-06" -uFormat "%Y-%m-%d %a Week: %V"
2013-01-06 Sun Week: 1
PS C:\Users\A730978F> get-date -date "2013-01-07" -uFormat "%Y-%m-%d %a Week: %V"
2013-01-07 Mon Week: 2
PS C:\Users\A730978F> get-date -date "2013-01-08" -uFormat "%Y-%m-%d %a Week: %V"
2013-01-08 Tue Week: 2

2014 - 周二:

PS C:\Users\A730978F> get-date -date "2014-01-05" -uFormat "%Y-%m-%d %a Week: %V"
2014-01-05 Sun Week: 1
PS C:\Users\A730978F> get-date -date "2014-01-06" -uFormat "%Y-%m-%d %a Week: %V"
2014-01-06 Mon Week: 1
PS C:\Users\A730978F> get-date -date "2014-01-07" -uFormat "%Y-%m-%d %a Week: %V"
2014-01-07 Tue Week: 2

2015 - 星期三:

PS C:\Users\A730978F> get-date -date "2015-01-04" -uFormat "%Y-%m-%d %a Week: %V"
2015-01-04 Sun Week: 1
PS C:\Users\A730978F> get-date -date "2015-01-05" -uFormat "%Y-%m-%d %a Week: %V"
2015-01-05 Mon Week: 1
PS C:\Users\A730978F> get-date -date "2015-01-06" -uFormat "%Y-%m-%d %a Week: %V"
2015-01-06 Tue Week: 1
PS C:\Users\A730978F> get-date -date "2015-01-07" -uFormat "%Y-%m-%d %a Week: %V"
2015-01-07 Wed Week: 2

(请注意,我没有尝试过每一年的所有星期)

编辑2:

再次查看示例后,似乎周数是基于已经过去的“7 天”的数量。我想它实际上根本没有使用任何“一周的第一天”设置。我想我得做一些相应的计算。

感谢您的帮助!

【问题讨论】:

标签: date powershell


【解决方案1】:

显然 powershell 参数 -uformat %V 实际上并没有使用任何类型的“一周的第一天”规则。它实际上只是显示自年初以来已经过去的“7 天”(从 1 开始)。

使用这些信息,我创建了以下函数,为一周中的每一天(周日到周六)检索相同的正确周数:

(感谢@DavidBrabant 和@vonPryz 提供我需要的其他信息)

Function GetWeekOfYear($date)
{
    # Note: first day of week is Sunday
    $intDayOfWeek = (get-date -date $date).DayOfWeek.value__
    $daysToWednesday = (3 - $intDayOfWeek)
    $wednesdayCurrentWeek = ((get-date -date $date)).AddDays($daysToWednesday)

    # %V basically gets the amount of '7 days' that have passed this year (starting at 1)
    $weekNumber = get-date -date $wednesdayCurrentWeek -uFormat %V

    return $weekNumber
}

$weekNumber = GetWeekOfYear (get-date)

(我使用了一个参数,所以函数更灵活/可测试)

这个函数基本上是根据一年中的第 n 个星期三获取星期数,并使用星期日作为一周的第一天(我没有花时间改变它,因为这实际上是我公司使用的惯例)。

您可以说它根据今年至少有 4 天的第一周检索周数,并且一周的第一天是星期日。

【讨论】:

    【解决方案2】:

    问题是由不同的全球化规则引起的。美国周数的计算方式与德国不同。

    为了获得预期的周编号,您必须使用全球化设置来拉动一些字符串。另一位SO question 详细讨论了该主题。

    【讨论】:

    • 感谢您的回答,第 53 周确实是我遇到的另一个问题。但是,这个问题实际上是关于根据星期几获得正确的星期数的问题(星期变化并不总是在星期日至星期一之间)
    【解决方案3】:

    在 PowerShell 7.x.y 中:

    [System.Globalization.ISOWeek]::GetWeekOfYear((get-date))
    

    在 PowerShell 5.x.y 中:

    function Get-ISOWeek {
      Param(
            [Parameter(
                # Mandatory,
                ValueFromPipeline,
                ValueFromPipelineByPropertyName,
                HelpMessage = 'Valid Date'
            )]
            [Alias('DT', 'DateTime')]
                [datetime[]]$Dates = (Get-Date),
            [Validateset('Culture', 'UICulture', 'InvariantCulture')]
            [string]$Culture
        )
        <#
            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.
        #>
        BEGIN {
            $Cult = Switch ($Culture) {
                'UICulture' {
                    Get-UICulture
                    Break
                }
                'InvariantCulture' {
                    [CultureInfo]::InvariantCulture
                    Break
                }
                default{
                    Get-Culture
                }
            }
            $WeekRule = $Cult.DateTimeFormat.CalendarWeekRule.value__
            $FirstDayOfWeek = $Cult.DateTimeFormat.FirstDayOfWeek.value__
        }
        PROCESS{
            ForEach ($DateElement in $Dates) {
                Try {
                    Write-Verbose "------------------------"
                    Write-Verbose "Try to turn $DateElement into ISO8601Week"
                    $WeekRuleDay = [int]($DateElement.DayOfWeek.Value__ -ge $FirstDayOfWeek ) * ( (6 - $WeekRule) - $DateElement.DayOfWeek.Value__ )
                    $WeekNumber = $Cult.Calendar.GetWeekOfYear(($DateElement).AddDays($WeekRuleDay), $WeekRule, $FirstDayOfWeek)
    <#
    I need to check the DayNumber formula. The FirstDayOfTheWeek must become 1
    In the Netherlands we start with Monday
    #>
                    $DayNumber = (7, 1, 2, 3, 4, 5, 6)[$($DateElement.DayOfWeek.value__ + 1)]
                    $Properties = @{
                        Date = Get-Date($DateElement)
                        LongDate = Get-Date($DateElement).ToLongDateString()
                        WeekRuleDay = $WeekRuleDay
                        WeekNumber = $WeekNumber
              ISOWeek    = "$($DateElement.Year)-W$WeekNumber"
              ISOWeekDay = "$($DateElement.Year)-W$WeekNumber-$DayNumber"
              ISO8601Week    = "$($DateElement.Year)-W$WeekNumber"
                        ISO8601WeekDay = "$($DateElement.Year)-W$WeekNumber-$DayNumber"
                    }
                } Catch {
                    Write-Verbose "Could not turn: $DateElement into ISO8601Week"
                    $Properties = @{
                        Date = $DateElement
                        LongDate = ''
                        WeekRuleDay = ''
                        WeekNumber = ''
              ISOWeek    = ''
              ISOWeekDay = ''
              ISO8601Week    = ''
                        ISO8601WeekDay = ''
                    }
                } Finally{
                    Write-Verbose "Final"
                    $Obj = New-Object -Typename PSCustomObject -Property $Properties
                    Write-Output $Obj
                }
                
            }
        }
        END{}
    }
    

    输出:

    (20..31).ForEach( { (Get-ISOWeek("2012-12-$($_)")).ISOWeekDay }) + ((1..7).ForEach( { (Get-ISOWeek("2013-1-$($_)")).ISOWeekDay })) -join ','
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      相关资源
      最近更新 更多