【问题标题】:Problem with Week Numbers between dates on New Year新年日期之间的周数问题
【发布时间】:2019-11-18 06:36:04
【问题描述】:

问题

以下 [mcve] 将输出两个日期之间的周数数组。它适用于两个日期在同一年,但是,有些年份有 52 周,并在去年的最后几天开始。而其他人则有 53 周。

52 周的示例是2020 calendar

第一周从 12 月 30 日开始。

53周的例子是2016 calendar

仅从 1 月 4 日开始。

代码

以下代码被注释并输出带有周数的数组。

Sub w_test()
    Dim Arr() As Variant, ArrDateW() As Variant
    'Initial Date
    DateI = DateSerial(2015, 5, 5)
    'Final Date
    DateF = DateSerial(2017, 9, 20)
    'Difference in weeks between DateI and DateF
    weekDif = DateDiff("ww", DateI, DateF) + k - 1

    i = Weekday(DateI)
    d = DateI

    'If not Sunday, go back to last week, to start the loop
    If i <> 1 Then
        d = DateAdd("d", -(i - 1), d)
    End If

    ReDim ArrDateW(weekDif)
    ReDim Arr(2)
    'Loop on all weeks between two dates to populate array of arrays
    For i = 0 To weekDif
        'Date
        Arr(0) = d
        'Trying to solve problem with New Year
        If Application.WorksheetFunction.WeekNum(d) = 53 Then
            flag = True
        End If
        If flag = False Then
            Arr(1) = Application.WorksheetFunction.WeekNum(d)
        Else
            Arr(1) = Application.WorksheetFunction.WeekNum(DateSerial(Year(d) + 1, 1, 1))
            flag = False
        End If

        'Year
        Arr(2) = Year(d)
        'Populate array of arrays
        ArrDateW(i) = Arr
        'Next Week Number
        d = DateAdd("ww", 1, d)
    Next i

    'To stop with Ctrl+F8
    Debug.Print d
End Sub

问题

2015 年有 53 周,但程序输出如下:

2016 and 2017之间,输出一团糟:

如何修复程序以正确输出这些周数?

【问题讨论】:

  • 如果年份是 2015,您是否尝试过使用 arrDateW(33)(2) = 53 的条件初始化?可以用这个变量来完成吗?
  • 我想让它充满活力,每年都在工作,就像在 2020 年一样。我已经坚持了几天......而且无法正确思考,所以我问了一个问题接收反馈或答案。
  • 按照我的看法,您可以 a) 按年自动化,使条件语言初始化该变量 - 即按年更改循环中变量的值或 b) 使用其他逻辑而不是“一年中的几个星期”。
  • 不管怎么说,365[.25] 天永远不会很好地分成 7 天一组。一个多世纪以前,零售商通过将一年分成 4 个季度,每个季度 13 周(分别为每月 3-4-3 周)解决了这个问题,并且每隔几年增加一个第 53 周;这样,每周的销售额总是与去年同期比较。第 53 周只是与第 1 周相比;考虑使用一个“日历”表来保存每个日期的元数据(DayOfWeek、WeekOfYear、WeekOfMonth、MonthOfYear、MonthOfQuarter 等) - 然后您就可以对任何内容进行时间聚合和比较。

标签: excel vba calendar week-number


【解决方案1】:

我的做法有些不同,依靠内置的 VBA 函数来正确计算周数。了解 ISO 周数是this answer,看看我是如何使用DataPart 函数的——不过如果你觉得有必要,你可以替换你自己的Ron de Bruin's ISO week number function 版本。

几个快速的旁注:

  1. Always use Option Explicit
  2. 尝试使用更具描述性的变量名称。你现在知道你在说什么了。几个月后,您将很难记住dArr 的含义(即使现在看起来很明显)。这只是一个好习惯,可以让代码自我记录。
  3. 我下面的示例将逻辑分解为一个带有可选参数的单独函数(只是为了好玩),它允许调用者将一周的开始时间更改为不同的日期。

代码模块:

Option Explicit

Sub w_test()
    Dim initialDate As Date
    Dim finaldate As Date
    initialDate = #5/5/2015#
    finaldate = #9/29/2017#

    Dim weeks As Variant
    weeks = WeekNumbers(initialDate, finaldate)

    Debug.Print "There are " & UBound(weeks, 1) & " weeks between " & _
                Format(initialDate, "dd-mmm-yyyy") & " and " & _
                Format(finaldate, "dd-mmm-yyyy")
End Sub

Private Function WeekNumbers(ByVal initialDate As Date, _
                             ByVal finaldate As Date, _
                             Optional ByVal weekStart As VbDayOfWeek = vbSunday) As Variant
    Dim numberOfWeeks As Long
    numberOfWeeks = DateDiff("ww", initialDate, finaldate, weekStart, vbFirstFullWeek)

    Dim startOfWeek As Date
    If Weekday(initialDate) <> vbSunday Then
        Dim adjustBy As Long
        If Weekday(initialDate) > weekStart Then
            adjustBy = Weekday(initialDate) - weekStart
        Else
            adjustBy = (Weekday(initialDate) + 7) - weekStart
        End If
        startOfWeek = DateAdd("d", -adjustBy, initialDate)
    End If

    Dim allTheWeeks As Variant
    ReDim allTheWeeks(1 To numberOfWeeks)

    Dim weekInfo As Variant
    ReDim weekInfo(1 To 3)

    Dim i As Long
    For i = 1 To numberOfWeeks
        weekInfo(1) = startOfWeek
        weekInfo(2) = DatePart("ww", startOfWeek, weekStart, vbFirstFourDays)
        weekInfo(3) = Year(startOfWeek)
        allTheWeeks(i) = weekInfo
        startOfWeek = DateAdd("ww", 1, startOfWeek)
    Next i

    WeekNumbers = allTheWeeks
End Function

【讨论】:

  • 我更新了答案中的代码,以说明一周中哪一天是第 1 天的所有情况。如果将 weekStart 参数更改为 vbMonday,它将为您提供第 53 周week(35).
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多