I recently needed routines to convert day/month/year to a day number for plotting, and back for anotation. I didn't immediately find rountines I liked, so I converted some Fortran code from a 1968 ACM publication.
Anything I have done here is free for all uses.
; date routines from
; "A machine algorithm for processing calendar dates"
; Henry F. Fliegel and Thomas C. Van Flandern
; Commun. ACM 11(10): 657 (1968)
; valid for all Gregorian calendar dates after November 23, -4713.
GetJulianDay proc gjdDay,gjdMonth,gjdYear ; returns (Julian) day number in eax
; JD=DD-32075+1461*(YYYY+4800+(MM-14)/12)/4
; , +367*(MM-2-((MM-14)/12)*12)/12
; , -3*((YYYY+4900+(MM-14)/12)/100)/4
;
push esi ; use for common term (MM-14)/12 which will be -1 or zero
xor eax,eax ; (MM-14)/12 == if MM<2 then = -1, else = 0
.if gjdMonth<3
dec eax ;-1
.endif
mov esi,eax ; save common amount
add eax,4800 ;DD-32075+1461*(YYYY+4800+(MM-14)/12)/4
add eax,gjdYear
imul eax,1461
shr eax,2
add eax,gjdDay
sub eax,32075
mov ecx,eax ; save partial
mov eax,esi ;+367*(MM-2-((MM-14)/12)*12)/12
imul eax,-12
sub eax,2
add eax,gjdMonth
imul eax,367
mov edx,0AAAAAAABh ; divide by 12
mul edx
shr edx,03h
add ecx,edx
mov eax,esi ;-3*((YYYY+4900+(MM-14)/12)/100)/4
add eax,4900
add eax,gjdYear
mov edx,051EB851Fh ; divide by 100
mul edx
shr edx,05h
lea eax,[edx+2*edx] ; * 3
shr eax,2
neg eax
add eax,ecx
pop esi
ret
GetJulianDay endp
align 4
GetDMY proc gdmyJulianDay ; returns eax=day, edx=month, ecx=year
; INTEGER JD,YYYY,MM,DD,L,N
; L=JD+68569
; N=4*L/146097
; L=L-(146097*N + 3)/4
; YYYY=4000*(L+1)/1461001
; L=L-1461*YYYY/4+31
; MM=80*L/2447
; DD=L-2447*MM/80
; L=MM/11
; MM=MM + 2 - 12*L
; YYYY=100*(N-49) + YYYY + L
; We will use ecx to contain L, esi to contain N
local gdmyYYYY,gdmyMM
push esi ; will contain N throughout
mov eax,gdmyJulianDay ; L=JD+68569
add eax,68569
mov ecx,eax ; keep L in ecx
shl eax,2 ; N=4*L/146097
mov edx,0396B06BDh ; div 146097
mul edx
shr edx,0Fh
mov eax,edx ; edx = quotient in magic divide
mov esi,eax
imul eax,146097 ; L=L-(146097*N + 3)/4
add eax,3
shr eax,2
sub ecx,eax
mov eax,ecx ; YYYY=4000*(L+1)/1461001
add eax,1
imul eax,4000
mov edx,0B7BBE2DDh ;div 1461001
mul edx
shr edx,014h
mov eax,edx
mov gdmyYYYY,eax
imul eax,1461 ; L=L-1461*YYYY/4+31
shr eax,2
neg eax
add eax,31
add ecx,eax
mov eax,ecx ; MM=80*L/2447
imul eax,80
mov edx,0D641E8C7h ; div 2447
mul edx
shr edx,0Bh
mov eax,edx
mov gdmyMM,eax
imul eax,2447 ; DD=L-2447*MM/80
mov edx,0CCCCCCCDh ; div 80
mul edx
shr edx,06h
neg edx
add edx,ecx
push edx ; save DD
mov eax,gdmyMM ; L=MM/11
mov edx,0BA2E8BA3h ; div 11
mul edx
shr edx,03h
mov eax,edx
mov ecx,eax
imul eax,-12 ; MM=MM + 2 - 12*L
add eax,2
add eax,gdmyMM
mov gdmyMM,eax
mov eax,esi ; YYYY=100*(N-49) + YYYY + L
sub eax,49
imul eax,100
add eax,gdmyYYYY
add ecx,eax ; final Year returned in ecx
pop eax ; get back DD. final day returned in eax
mov edx,gdmyMM ; final month returned in edx
pop esi
ret
GetDMY endp
This code is only slightly optimized, so feel free to post improvements.