如何告诉访问日期是 week/year
How to tell access that date is a week/year
如何告诉访问查询我在单元格中的日期是 weeks/year?前任。 5/2015 是 2015 年的第 5 周。
我试过 format([TheDate]; "ww/yyyy")
但它随后将 5/2015 转换为 2015 年 5 月的第一周 (20/2015)
这只是 12 周以下的问题,因为它们会在第 13-52 周正常通过,因为只有 12 个月:P
I have tried format([TheDate]; "ww/yyyy") but it then converts 5/2015
to the first week of may in 2015 (20/2015)
发生这种情况的原因是您将日期传递给 Format()
函数。您传递的日期是 5/2015
,Access 认为它是 2015 年 5 月(可能是 5 月 1 日)。然后,格式函数将该日期格式化为您指定的 "ww/yyyy"
格式,正确地说,是 20/2015。
这只是访问访问。对您的数据做出假设,而不是抛出错误或让您隐式定义事物。
可能有多种方法可以在公式中执行此操作。真是丑陋的方式。相反,您可以使用 UDF 解决它:
Function Week2Date(weekyear As String) As Date
Dim arrWeekYear As Variant
Dim dateJan1 As Date
Dim Sub1 As Boolean
'Split the incoming weekyear by "/" to an array
arrWeekYear = Split(weekyear, "/")
'determine the first of the year
dateJan1 = DateSerial(arrWeekYear(1), 1, 1)
'Add the weeks to the date and dance a little jig
Sub1 = (Format(dateJan1, "ww", vbUseSystem, vbUseSystem) = 1)
Week2Date = DateAdd("ww", arrWeekYear(0) + Sub1, dateJan1)
Week2Date = Week2Date - Weekday(Week2Date) + 7
End Function
这将采用您拥有的文本日期格式 "ww/yyyy" 并将其转换为实际日期。由于您必须做出一些假设才能将 7 天的时间段转换为一个日期,这应该会让您接近但您可能需要稍微调整一下以获得您想要的确切日期(比如......也许你只想从第一个完整周开始计数,然后使用每周的星期一作为返回日期)。
您首先需要一个将周-年解析为该周日期的函数。这并不容易,因为有些周跨越了日历年的边界,并且 VBA 无法正确计算某些年份的第 53 周:
Public Function ISO_DateOfWeek( _
ByVal intYear As Integer, _
ByVal bytWeek As Byte, _
Optional ByVal bytWeekday As Byte = vbMonday) _
As Date
' Calculates date of requested weekday in a week of
' a year according to ISO 8601:1988 standard.
'
' Notes: Years less than 100 will be handled as
' two-digit years of our current year frame.
' Years less than zero returns a zero date.
' A weeknumber of zero returns the requested
' weekday of the week before week 1.
'
' 2000-12-17. Cactus Data ApS, Gustav Brock.
' The fourth of January is always included in
' the first week of year intYear.
Const cbytDayOfFirstWeek As Byte = 4
' Number of days in a week.
Const cbytDaysOfWeek As Byte = 7
' Month of January.
Const cbytJanuary As Byte = 1
Dim datDateOfFirstWeek As Date
Dim intISOMonday As Integer
Dim intISOWeekday As Integer
Dim intWeekdayOffset As Integer
' No specific error handling.
On Error Resume Next
If intYear > 0 Then
' Weekday of Monday.
intISOMonday = Weekday(vbMonday, vbMonday)
' Date of fourth of January in year intYear.
datDateOfFirstWeek = DateSerial(intYear, cbytJanuary, cbytDayOfFirstWeek)
' Weekday of fourth of January in year intYear.
intISOWeekday = Weekday(datDateOfFirstWeek, vbMonday)
' Calculate offset from Monday in first week of year intYear.
intWeekdayOffset = intISOMonday - intISOWeekday
' Weekday of requested weekday.
intISOWeekday = Weekday(bytWeekday, vbMonday)
' Calculate offset from requested weekday in first week of year intYear.
intWeekdayOffset = intWeekdayOffset + intISOWeekday - intISOMonday
' Date of requested weekday in first week of year intYear.
datDateOfFirstWeek = DateAdd("d", intWeekdayOffset, datDateOfFirstWeek)
' Date of requested weekday in requested week of year intYear.
datDateOfFirstWeek = DateAdd("ww", bytWeek - 1, datDateOfFirstWeek)
End If
ISO_DateOfWeek = datDateOfFirstWeek
End Function
然后是正确格式化的函数:
Public Function ISO_WeekYearNumber( _
ByVal datDate As Date, _
Optional ByRef intYear As Integer, _
Optional ByRef bytWeek As Byte) _
As String
' Calculates and returns year and week number for date datDate according to the ISO 8601:1988 standard.
' Optionally returns numeric year and week.
' 1998-2007, Gustav Brock, Cactus Data ApS, CPH.
' May be freely used and distributed.
Const cbytFirstWeekOfAnyYear As Byte = 1
Const cbytLastWeekOfLeapYear As Byte = 53
Const cbytMonthJanuary As Byte = 1
Const cbytMonthDecember As Byte = 12
Const cstrSeparatorYearWeek As String = "W"
Dim bytMonth As Byte
Dim bytISOThursday As Byte
Dim datLastDayOfYear As Date
intYear = Year(datDate)
bytMonth = Month(datDate)
bytWeek = DatePart("ww", datDate, vbMonday, vbFirstFourDays)
If bytWeek = cbytLastWeekOfLeapYear Then
bytISOThursday = Weekday(vbThursday, vbMonday)
datLastDayOfYear = DateSerial(intYear, cbytMonthDecember, 31)
If Weekday(datLastDayOfYear, vbMonday) >= bytISOThursday Then
' OK, week count of 53 is caused by leap year.
Else
' Correct for Access97/2000+ bug.
bytWeek = cbytFirstWeekOfAnyYear
End If
End If
' Adjust year where week number belongs to next or previous year.
If bytMonth = cbytMonthJanuary Then
If bytWeek >= cbytLastWeekOfLeapYear - 1 Then
' This is an early date of January belonging to the last week of the previous year.
intYear = intYear - 1
End If
ElseIf bytMonth = cbytMonthDecember Then
If bytWeek = cbytFirstWeekOfAnyYear Then
' This is a late date of December belonging to the first week of the next year.
intYear = intYear + 1
End If
End If
ISO_WeekYearNumber = CStr(intYear) & cstrSeparatorYearWeek & Format(bytWeek, "00")
End Function
当然,您可以修改最后一个函数以提供所需的字符串。
如何告诉访问查询我在单元格中的日期是 weeks/year?前任。 5/2015 是 2015 年的第 5 周。
我试过 format([TheDate]; "ww/yyyy")
但它随后将 5/2015 转换为 2015 年 5 月的第一周 (20/2015)
这只是 12 周以下的问题,因为它们会在第 13-52 周正常通过,因为只有 12 个月:P
I have tried format([TheDate]; "ww/yyyy") but it then converts 5/2015 to the first week of may in 2015 (20/2015)
发生这种情况的原因是您将日期传递给 Format()
函数。您传递的日期是 5/2015
,Access 认为它是 2015 年 5 月(可能是 5 月 1 日)。然后,格式函数将该日期格式化为您指定的 "ww/yyyy"
格式,正确地说,是 20/2015。
这只是访问访问。对您的数据做出假设,而不是抛出错误或让您隐式定义事物。
可能有多种方法可以在公式中执行此操作。真是丑陋的方式。相反,您可以使用 UDF 解决它:
Function Week2Date(weekyear As String) As Date
Dim arrWeekYear As Variant
Dim dateJan1 As Date
Dim Sub1 As Boolean
'Split the incoming weekyear by "/" to an array
arrWeekYear = Split(weekyear, "/")
'determine the first of the year
dateJan1 = DateSerial(arrWeekYear(1), 1, 1)
'Add the weeks to the date and dance a little jig
Sub1 = (Format(dateJan1, "ww", vbUseSystem, vbUseSystem) = 1)
Week2Date = DateAdd("ww", arrWeekYear(0) + Sub1, dateJan1)
Week2Date = Week2Date - Weekday(Week2Date) + 7
End Function
这将采用您拥有的文本日期格式 "ww/yyyy" 并将其转换为实际日期。由于您必须做出一些假设才能将 7 天的时间段转换为一个日期,这应该会让您接近但您可能需要稍微调整一下以获得您想要的确切日期(比如......也许你只想从第一个完整周开始计数,然后使用每周的星期一作为返回日期)。
您首先需要一个将周-年解析为该周日期的函数。这并不容易,因为有些周跨越了日历年的边界,并且 VBA 无法正确计算某些年份的第 53 周:
Public Function ISO_DateOfWeek( _
ByVal intYear As Integer, _
ByVal bytWeek As Byte, _
Optional ByVal bytWeekday As Byte = vbMonday) _
As Date
' Calculates date of requested weekday in a week of
' a year according to ISO 8601:1988 standard.
'
' Notes: Years less than 100 will be handled as
' two-digit years of our current year frame.
' Years less than zero returns a zero date.
' A weeknumber of zero returns the requested
' weekday of the week before week 1.
'
' 2000-12-17. Cactus Data ApS, Gustav Brock.
' The fourth of January is always included in
' the first week of year intYear.
Const cbytDayOfFirstWeek As Byte = 4
' Number of days in a week.
Const cbytDaysOfWeek As Byte = 7
' Month of January.
Const cbytJanuary As Byte = 1
Dim datDateOfFirstWeek As Date
Dim intISOMonday As Integer
Dim intISOWeekday As Integer
Dim intWeekdayOffset As Integer
' No specific error handling.
On Error Resume Next
If intYear > 0 Then
' Weekday of Monday.
intISOMonday = Weekday(vbMonday, vbMonday)
' Date of fourth of January in year intYear.
datDateOfFirstWeek = DateSerial(intYear, cbytJanuary, cbytDayOfFirstWeek)
' Weekday of fourth of January in year intYear.
intISOWeekday = Weekday(datDateOfFirstWeek, vbMonday)
' Calculate offset from Monday in first week of year intYear.
intWeekdayOffset = intISOMonday - intISOWeekday
' Weekday of requested weekday.
intISOWeekday = Weekday(bytWeekday, vbMonday)
' Calculate offset from requested weekday in first week of year intYear.
intWeekdayOffset = intWeekdayOffset + intISOWeekday - intISOMonday
' Date of requested weekday in first week of year intYear.
datDateOfFirstWeek = DateAdd("d", intWeekdayOffset, datDateOfFirstWeek)
' Date of requested weekday in requested week of year intYear.
datDateOfFirstWeek = DateAdd("ww", bytWeek - 1, datDateOfFirstWeek)
End If
ISO_DateOfWeek = datDateOfFirstWeek
End Function
然后是正确格式化的函数:
Public Function ISO_WeekYearNumber( _
ByVal datDate As Date, _
Optional ByRef intYear As Integer, _
Optional ByRef bytWeek As Byte) _
As String
' Calculates and returns year and week number for date datDate according to the ISO 8601:1988 standard.
' Optionally returns numeric year and week.
' 1998-2007, Gustav Brock, Cactus Data ApS, CPH.
' May be freely used and distributed.
Const cbytFirstWeekOfAnyYear As Byte = 1
Const cbytLastWeekOfLeapYear As Byte = 53
Const cbytMonthJanuary As Byte = 1
Const cbytMonthDecember As Byte = 12
Const cstrSeparatorYearWeek As String = "W"
Dim bytMonth As Byte
Dim bytISOThursday As Byte
Dim datLastDayOfYear As Date
intYear = Year(datDate)
bytMonth = Month(datDate)
bytWeek = DatePart("ww", datDate, vbMonday, vbFirstFourDays)
If bytWeek = cbytLastWeekOfLeapYear Then
bytISOThursday = Weekday(vbThursday, vbMonday)
datLastDayOfYear = DateSerial(intYear, cbytMonthDecember, 31)
If Weekday(datLastDayOfYear, vbMonday) >= bytISOThursday Then
' OK, week count of 53 is caused by leap year.
Else
' Correct for Access97/2000+ bug.
bytWeek = cbytFirstWeekOfAnyYear
End If
End If
' Adjust year where week number belongs to next or previous year.
If bytMonth = cbytMonthJanuary Then
If bytWeek >= cbytLastWeekOfLeapYear - 1 Then
' This is an early date of January belonging to the last week of the previous year.
intYear = intYear - 1
End If
ElseIf bytMonth = cbytMonthDecember Then
If bytWeek = cbytFirstWeekOfAnyYear Then
' This is a late date of December belonging to the first week of the next year.
intYear = intYear + 1
End If
End If
ISO_WeekYearNumber = CStr(intYear) & cstrSeparatorYearWeek & Format(bytWeek, "00")
End Function
当然,您可以修改最后一个函数以提供所需的字符串。