I was redesigning an old calendar app of mine, and I needed a code that would calculate the DoY (Day of Year, 1-366) WITHOUT accessing any hardcoded values or variables, so I came up with this. It takes into account leap years, according to the Gregorian calendar rules (years divisible by 4 are leap, but years divisible by 100 are not leap, unless they are also divisible by 400), so it will produce correct results for any date in the Gregorian calendar (after 1582 AD, or whatever year the Gregorian calendar was adopted in your country). Expects the year (>1581) in eax, the month (1-12) in ecx and the day (1-31) in edx, returns the DoY in eax. Does not check for date validity. Preserves Windows registers. Currently I've tried to use as few instructions as possible, so speed or size optimizations are possible. It would be nice if someone could reduce the number of instructions.

push ebx
dec ecx
mov ebx, ecx
imul ecx, 30
test ebx, 9
jnz @F
dec ecx
@@: shr ebx, 1
jnz @F
add ecx, 2
@@: add ecx, ebx
cmp ecx, 32
lea ecx, [ecx+edx-1]
jna Done
test eax, 3
jnz Done
xor edx, edx
mov ebx, 100
div ebx
cmp edx, 0
jnz @F
and eax, 3
jnz Done
@@: inc ecx
Done: mov eax, ecx
pop ebx
Posted on 2002-03-18 08:49:01 by micmic