ISO weeknumber
ISO weeknumber
I'm looking for a good example how to calculate the ISO weeknumber. I've been looking in the forum, as well as checking out the internet, and thus far I've seen many examples, but none I could understand or convert.
Would anyone have a snippet handy of sample code?
Would anyone have a snippet handy of sample code?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
Re: ISO weeknumber
The week that contains january 4 is week 1.
ISO weeks start on monday.
So maybe you could use DayOfWeek(Date) to check what kind of day january 4 of a year was (monday, tuesday etc.), and use that to determine the start of week 1.
One you know the start of week 1, you could determine the week of another date in that year be taking the difference in time stamp to see how many weeks have passed.
ISO weeks start on monday.
So maybe you could use DayOfWeek(Date) to check what kind of day january 4 of a year was (monday, tuesday etc.), and use that to determine the start of week 1.
One you know the start of week 1, you could determine the week of another date in that year be taking the difference in time stamp to see how many weeks have passed.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: ISO weeknumber
Hello blueznl. Here's a simple implementation of the ISO 8601 week calculator:blueznl wrote:I'm looking for a good example how to calculate the ISO weeknumber.
Code: Select all
Procedure ISOWeek(date)
year = Year(date)
firstDay = DayOfWeek(Date(year, 1, 1, 0, 0, 0))
If firstDay = 0
firstDay = 7
EndIf
If firstDay <= 4
ISOday = DayOfYear(date) + (firstDay - 1)
Else
ISOday = DayOfYear(date) - (8 - firstDay)
EndIf
ISOwk = Round(ISOday / 7, #PB_Round_Up)
If Not ISOwk
ISOwk = ISOWeek(Date(year - 1, 12, 31, 0, 0, 0))
EndIf
;------
If ISOwk = 53 And Month(date) = 12 And
DayOfWeek(Date(year + 1, 1, 1, 0, 0, 0)) <= 4
ISOwk = 1
EndIf
;------
ProcedureReturn ISOWk
EndProcedure
Debug ISOWeek(Date())
Debug ISOWeek(Date(1997, 12, 29, 0, 0, 0)) ;week #1
Debug ISOWeek(Date(2012, 12, 31, 0, 0, 0)) ;week #1
Debug ISOWeek(Date(2012, 1, 1, 0, 0, 0)) ;week #52
Debug ISOWeek(Date(2016, 1, 1, 0, 0, 0)) ;week #53
EDIT: Code fixed to include a missing 53rd-week check, thanks to testing by Little John.
Last edited by TI-994A on Mon Aug 12, 2013 4:43 pm, edited 1 time in total.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel
Re: ISO weeknumber
Here's my attempt after some thinking
Code: Select all
Procedure.i WeekNumberISO(year, month, day)
Protected week1_prev, week1_this, week1_next
Protected specified_date = Date(year, month, day, 0, 0, 0)
week1_prev = Date(year - 1, 1, 4, 0, 0, 0)
week1_this = Date(year , 1, 4, 0, 0, 0)
week1_next = Date(year + 1, 1, 4, 0, 0, 0)
week1_prev - ((DayOfWeek(week1_prev) + 6) % 7) * 86400
week1_this - ((DayOfWeek(week1_this) + 6) % 7) * 86400
week1_next - ((DayOfWeek(week1_next) + 6) % 7) * 86400
If specified_date < week1_this
; still in last week of previous year
ProcedureReturn (specified_date - week1_prev) / 604800 + 1
ElseIf specified_date >= week1_next
; already in week 1 of next year
ProcedureReturn 1
Else
ProcedureReturn (specified_date - week1_this) / 604800 + 1
EndIf
EndProcedure
MessageRequester("", Str(WeekNumberISO(2013, 08, 11)))
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: ISO weeknumber
@TI-994A & @wilbert : Interesting code. Thanks for sharing.
➽ Windows 11 64-bit - PB 6.0 x64 - AMD Ryzen 7 - NVIDIA GeForce GTX 1650 Ti
Sorry for my bad english and the Dunning–Kruger effect.
-
- Addict
- Posts: 4527
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: ISO weeknumber
Here is my version.
//edit: Code improved.
//edit: Code improved.
Code: Select all
EnableExplicit
Procedure.i ISOdayOfWeek (date.i)
Protected d.i
d = DayOfWeek(date)
If d = 0
d = 7 ; for Sunday, return 7 instead of 0
EndIf
ProcedureReturn d
EndProcedure
Procedure.i ISOweek (date.i)
; The calculations are based on the fact that the first week of a year
; always contains January 4.
; [according to http://en.wikipedia.org/wiki/Seven-day_week#Week_numbering
; or better http://de.wikipedia.org/wiki/Woche#Kalenderwoche]
Protected doy.i=DayOfYear(date), year.i=Year(date)
Protected lastPrev.i ; last day of last week of previous year
Protected lastThis.i ; last day of last week of current year
lastPrev = 4 - ISOdayOfWeek(Date(year, 1, 4, 0,0,0))
lastThis = 4 - ISOdayOfWeek(Date(year,12,28, 0,0,0)) + DayOfYear(Date(year,12,31, 0,0,0))
If doy <= lastThis
If doy <= lastPrev
; The given day is in the last week of the previous year.
doy + DayOfYear(Date(year-1,12,31, 0,0,0))
lastPrev = 4 - ISOdayOfWeek(Date(year-1,1,4, 0,0,0))
EndIf
ProcedureReturn Round((doy-lastPrev)/7, #PB_Round_Up)
Else
; The given day is in the first week of the next year.
ProcedureReturn 1
EndIf
EndProcedure
; -- Demo
Debug ISOweek(Date(2009,12,31, 0,0,0)) ; 53
Debug ISOweek(Date(2010, 1, 1, 0,0,0)) ; 53
Debug ISOweek(Date(2010, 1, 2, 0,0,0)) ; 53
Debug ISOweek(Date(2010, 1, 3, 0,0,0)) ; 53
Debug ISOweek(Date(2010, 1, 4, 0,0,0)) ; 1
Debug ISOweek(Date(2010,12,31, 0,0,0)) ; 52
Debug ISOweek(Date(2011, 1, 1, 0,0,0)) ; 52
Debug ISOweek(Date(2011, 1, 2, 0,0,0)) ; 52
Debug ISOweek(Date(2011, 1, 3, 0,0,0)) ; 1
Debug ISOweek(Date(2011,12,31, 0,0,0)) ; 52
Debug ISOweek(Date(2012, 1, 1, 0,0,0)) ; 52
Debug ISOweek(Date(2012, 1, 2, 0,0,0)) ; 1
Debug ISOweek(Date(2012,12,30, 0,0,0)) ; 52
Debug ISOweek(Date(2012,12,31, 0,0,0)) ; 1
Last edited by Little John on Mon Aug 12, 2013 11:38 am, edited 1 time in total.
-
- Addict
- Posts: 4527
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: ISO weeknumber
Hi TI-994A,
I think I've found a bug in your code.
Try
That yields 53, but it should be 1 (according to my paper calendar, or e.g. to this webpage).
I think I've found a bug in your code.
Try
Code: Select all
Debug ISOWeek(Date(2012,12,31, 0,0,0))
Re: ISO weeknumber
Hello Little John. You're right; thank you for the catch. I've modified the code in my earlier post, and it now includes a check to validate the 53rd week.Little John wrote:I think I've found a bug in your code.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel
Re: ISO weeknumber
The brilliance in this forum never fails to amaze me... thanks all! (Weeknumber made it into my little graphical experiment.)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
- Michael Vogel
- Addict
- Posts: 2677
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: ISO weeknumber
I did a short one including some prime numbers...
Code: Select all
Procedure ISOWeek(date)
date=date/86400+3
ProcedureReturn (date-(Date(Year((date-date%7)*86400),1,date%7+5,0,0,0)/86400-11))/7
EndProcedure
Debug ISOWeek(Date())
Debug ISOWeek(Date(1997, 12, 29, 0, 0, 0)) ;week #1
Debug ISOWeek(Date(2012, 12, 31, 0, 0, 0)) ;week #1
Debug ISOWeek(Date(2012, 1, 1, 0, 0, 0)) ;week #52
Debug ISOWeek(Date(2016, 1, 1, 0, 0, 0)) ;week #53
Re: ISO weeknumber
Sorry, Mickael, your code is wrong, I just discovered it today (I was using your snipet in a software ^^)
Today we are in the 35 week and your snipet gives 36...
Too bad, your solution was pretty elegant...
Today we are in the 35 week and your snipet gives 36...
Too bad, your solution was pretty elegant...
There are 2 methods to program bugless.
But only the third works fine.
Win10, Pb x64 5.71 LTS
But only the third works fine.
Win10, Pb x64 5.71 LTS