May 24, 2024, 05:04:45 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Week Of Year

Started by ckoehn, March 23, 2010, 10:12:14 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ckoehn

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

ZeroDog

March 23, 2010, 03:23:13 PM #1 Last Edit: March 23, 2010, 03:25:04 PM by ZeroDog
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.

ckoehn

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

ckoehn

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

celphick

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



Johnny

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

ckoehn

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