I need to be able to send a sub the date and have it return the week number (1-52) of that year. Where would I look or how would I go about doing that?
Thanks for your help.
Clint
I suppose you would have to take the date, and calculate what day of the year it is based on the month and day, and then divide that number by the number of days in a week. You might need to factor in leap years as well.
March 23 2010
March is the 3rd month so we count the days in the first 2 months, january has 31 days, february has 28 days. Add the 23rd day of the month. Divide by 7 days per week.
(31+28+23) / 7 = 11.71
Round it off to the 11th week.
Thanks for your input ZeroDog.
I was trying to use FileTime to do the calculations. Set a SystemTime to the date I need the week for.
Set another SystemTime to year of the date that I need the week for and the 1st month 1st day.
Convert both to FileTime and subtract the smaller from the larger and then divide by 7 days.
Some reason I'm getting a weird number that I'm not expecting. Thought it should be a 1 to 2 digit number... still working on it.
SUB WeekNumber(INT Year, INT Month, INT Day),INT
SYSTEMTIME stime,sttime
UINT64 ftime,fttime,vartime
INT weekd
stime.wYear=Year
stime.wMonth=1
stime.wDay=1
SystemTimeToFileTime(stime,ftime)
sttime.wYear=Year
sttime.wMonth=Month
sttime.wDay=Day
SystemTimeToFileTime(sttime,fttime)
vartime=(fttime-ftime)/(7q*1440q*60q*10000000q) 'difference divided by 7 days
MESSAGEBOX 0,STR$(vartime),"Week Number"
week=vartime 'number of weeks? Need to return an integer
RETURN week
ENDSUB
This is based on ZeroDog's logic which I agree with. This seems to work.
SUB WeekNumber(INT Year, INT Month, INT Day),INT
INT Days,wi,Week
Days=0
IF Month>1
FOR wi=1 TO Month-1
Days+=DaysInMonth(Year,Month)
NEXT wi
Days+=Day
ELSE
Days=Day
ENDIF
Week=(Days/7)+1
RETURN Week
ENDSUB
SUB DaysInMonth(INT Year, INT Month),INT
INT Day
Day=VAL(MID$("312831303130313130313031",(Month-1)*2+1,2))
IF (Year % 4)=0 'leap year
IF Month=2
Day+=1
ENDIF
ENDIF
RETURN Day
ENDSUB
Zerodog's method is adequate as far as ckoehn's program is concerned.
The only reason I'm replying is that someone doing a search and needing a method for a business application, requires a different method, where a week starts on Monday and some early days in January may be considered as part of the previous year.
QuoteCopied from the calendar FAQ [http://www.tondering.dk/claus/calendar.html]
For dates in January and February, calculate:
a = year - 1
b = a/4 - a/100 + a/400
c = (a-1)/4 - (a-1)/100 + (a-1)/400
s = b - c
e = 0
f = day - 1 + 31 * (month - 1)
For dates in March through December, calculate:
a = year
b = a/4 - a/100 + a/400
c = (a-1)/4 - (a-1)/100 + (a-1)/400
s = b - c
e = s + 1
f = day + (153ÃÆ'ââ,¬â€(month-3)+2)/5 + 58 + s
Then, for any month continue thus:
g = (a + b) mod 7
d = (f + g - e) mod 7
n = f + 3 - d
We now have three situations:
If n < 0, the day lies in week 53 - (g-s)/5 of the previous year.
If n > 364 + s, the day lies in week 1 of the coming year.
Otherwise, the day lies in week n/7 + 1 of the current year.
This algorithm gives you a couple of additional useful values:
d indicates the day of the week (0=Monday, 1=Tuesday, etc.)
f + 1 is the ordinal number of the date within the current year.
Note: all divisions are integer divisions with no remainder.
This code is just a quick direct translation of the quote for a subroutine in EB.
' prog_name : sub_week_of_year.exe
' version : v 00.00.01
' commenced : 2010/03/24
' last change : 2010/03/24
' compile as : Console EXE, Emergence Basic
' purpose : to generate ISO week of the year
autodefine "off"
' VARIABLES
int yr, mn, dy
openconsole
input "Year = ", yr
input "Month = ", mn
input "Day = ", dy
print
print "Week of year = ",week_of_year(yr, mn, dy)
do : until inkey$<>""
closeconsole
end
'********************* SUBROUTINES ************************
sub week_of_year(year as int, month as int, day as int), int
' int year, month, day
int a, b, c, s, e, f, g, d, n, ret
if month <= 2
a = year - 1
else
a = year
endif
b = a/4 - a/100 + a/400
c = (a-1)/4 - (a-1)/100 + (a-1)/400
s = b - c
if month <= 2
e = 0
f = day - 1 + 31 * (month - 1)
else
e = s + 1
f = day + (153*(month-3)+2)/5 + 58 + s
endif
g = (a + b) % 7
d = (f + g - e) % 7
n = f + 3 - d
select 1
case n<0
ret = 53 - (g - s)/5 : ' previous year
ret = -ret : 'this is to show it was the previous year (only for January).
case n>364+s
ret = 1
default
ret = n/7 + 1
endselect
return ret
endsub : ' week_of_year
I agree Celphick, you are correct.
Meanwhile I translated an old QBasic program I wrote about 30 years ago... It took me a while to translate, that's why my reply is very late. ;D
You can do more things with that approach, like calculating the number of days between two dates etc...
Maybe useful for somebody?
Johnny
' Week / weekday calendar in accordance with the ISO standard (First day of week = Monday, Week 1 is the week with the first thursday in it)
AUTODEFINE "OFF"
DECLARE "kernel32",Sleep(dwMilliseconds:INT)
DEF Day,Month,Year,Days,DaysNY,Week,WeekNY,Weekday,WeekdayNY:INT
DEF DayNames[7]:STRING
'Initialize the 7 weekday names
DayNames = "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"
OPENCONSOLE
CLS
INPUT "Day = ",Day
INPUT "Month = ",Month
INPUT "Year = ",Year
PRINT
DaysNY = GetDay(1,1,Year)
WeekdayNY = DaysNY % 7
WeekNY = (WeekdayNY < 4)
IF WeekNY = 0 THEN WeekNY = 52 + (INT(GetDay(1,1,Year - 1) % 7) < 4)
PRINT "New years day",STR$(Year)," = ",DayNames[WeekdayNY % 7]," / Week ",WeekNY
PRINT
Days = GetDay(Day,Month,Year)
Weekday = Days % 7
Week = INT(Days / 7) - INT(DaysNY / 7)
IF WeekdayNY < 4 THEN Week = Week + 1
IF Week = 0 THEN Week = WeekNY
PRINT "Date : ",MID$(STR$(Day),2),"/",MID$(STR$(Month),2),"/",MID$(STR$(Year),2)," = ",DayNames[Days % 7]," / Week ",Week
PRINT
PRINT "Press any key to continue..."
WHILE INKEY$ = ""
Sleep(100)
ENDWHILE
CLOSECONSOLE
END
SUB GetDay(D as INT,M as INT,Y as INT), INT
DEF N,Y2:INT
Y2 = Y - (M < 3)
N = 365 * Y + D + 31 * M + 2 - (M >= 3) * INT(.4 * M + 2.3) + INT(Y2 / 4) - INT(.75 + INT(Y2 / 100) * .75)
RETURN N
ENDSUB
Thank you all for your help. I needed to do some more work on mine. The week needs to end on Saturday evening. Sunday is the start of another week. I'm going to digest both of your programs.
Later,
Clint