Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

CALENDAR.ASM

Calendar


; =============================================================================
;
;                        Litos - Calendar, date and time
;
; =============================================================================
; Julian date: days from 1/1/4713 BCE noon 12:00 (it was Monday)
; Julian date has period 7980 years, than start year 1 again.
; Julian date range: 1/1/4713 BCE 12:00 to 1/1/3268 CE 12:00, e.g. 0 to 2914673
; days. Julian period is 2518277472000000000 100-nanoseconds (e.g. 7980 years).
;
; Julian calendar: till Thursday 10/4/1582 (begins julian date 2299159.5)
; Gregorian calendar: from Friday 10/15/1582 (begins julian date 2299160.5)
; 1/1/1 CE: JD=1721423.5, Saturday (there is no year 0!)
; 1/1/1 BCE: JD=1721057.5 Thursday
; Julian year: 365.25 days, Gregorian year: 365.2425 days.
;
; ISO-8601: date format YYYY-WW-DD (year-week-day_of_week). Week: 1 to 53,
; day of week: 1 to 7, 1=Monday. First week of year is such a week, which 
; contains first Thursday of Gregorian year, and week containing January 4th.
;
; Normal year, 365 days:
;    Mo  Tu  We  Th  Fr  Sa  Su
;                             1  no   1 + 51*7 + 7 yes, 52, 4.1. is Th
;	                  1   2  no   2 + 51*7 + 6 yes, 52, 4.1. is We
;                     1   2   3  no   3 + 51*7 + 5 yes, 52, 4.1. is Tu
;                 1   2   3   4  yes  4 + 51*7 + 4 yes, 53, 4.1. is Mo
;            1    2   3   4   5  yes  5 + 51*7 + 3 no,  52, 4.1. is Su
;        1   2    3   4   5   6  yes  6 + 51*7 + 2 no,  52, 4.1. is Sa
;    1   2   3    4   5   6   7  yes  7 + 51*7 + 1 no,  52, 4.1. is Fr
;
; Leap year, 366 days:
;    Mo  Tu  We  Th  Fr  Sa  Su
;                             1  no   1 + 52*7 + 1 no,  52, 4.1. is Fr
;	                  1   2  no   2 + 51*7 + 7 yes, 52, 4.1. is Th
;                     1   2   3  no   3 + 51*7 + 6 yes, 52, 4.1. is We
;                 1   2   3   4  yes  4 + 51*7 + 5 yes, 53, 4.1. is Tu
;            1    2   3   4   5  yes  5 + 51*7 + 4 yes, 53, 4.1. is Mo
;        1   2    3   4   5   6  yes  6 + 51*7 + 3 no,  52, 4.1. is Su
;    1   2   3    4   5   6   7  yes  7 + 51*7 + 2 no,  52, 4.1. is Fr
;
; Year 1582 has 355 days (it is not leap), 51 weeks.
; =============================================================================

		CODE_SECTION	32

; -----------------------------------------------------------------------------
;                     Convert system time to Julian time
; -----------------------------------------------------------------------------
; INPUT:	EBX = system time structure (see SYSTIME: only time and date
;			entries are used. Flags, week, day in year and day
;			of week are ignored)
; OUTPUT:	EDX:EAX = Julian time (100-nanosec from 1/1/4713 BCE 12:00)
;			Value is in range from 0 to 2518277471999999999.
; NOTES:	Entries are taken as signed and their overlaps are accounted.
; 		Takes 150 ns on 1.6 GHz CPU.
; -----------------------------------------------------------------------------
; On whole function: ESI = system time structure, EBP:EDI = accumulator.

; ------------- Push registers

SystemToJulian:	push	ebx		; push EBX
		push	ecx		; push ECX
		push	esi		; push ESI
		push	edi		; push EDI
		push	ebp		; push EBP
		mov	esi,ebx		; ESI <- system time structure

; ------------- Sum seconds and 100-nanoseconds (-> EBP:EDI)

		movsx	eax,byte [esi+SYSTIME_Sec] ; EAX <- seconds
		mov	ecx,10000000	; ECX <- 100-nanoseconds per second
		imul	ecx		; EAX <- recalc seconds to 100-nanosec
		add	eax,[esi+SYSTIME_100NSec] ; add 100-nanoseconds
		adc	edx,byte 0	; overflow
		xchg	eax,edi		; EDI <- accumulator LOW
		mov	ebp,edx		; EBP <- accumulator HIGH

; ------------- Sum hours and minutes (add to EBP:EDI)

		movsx	eax,byte [esi+SYSTIME_Hour] ; EAX <- hours
		sub	eax,byte 12	; time correction
		xor	ecx,ecx		; ECX <- 0
		mov	cl,60		; ECX <- 60, minutes per hour
		imul	ecx		; EAX <- minutes
		movsx	ecx,byte [esi+SYSTIME_Min] ; ECX <- minutes
		add	eax,ecx		; EAX <- hours + minutes
		mov	ecx,60*10000000 ; ECX <- 100-nanoseconds per minute
		imul	ecx		; recalc minutes to 100-nanoseconds
		add	edi,eax		; add minutes to accumulator LOW
		adc	ebp,edx		; add minutes to accumulator HIGH

; ------------- Carry month (-> EAX) to year (-> ECX)

		movsx	eax,byte [esi+SYSTIME_Month] ; EAX <- month
		dec	eax		; EAX <- change month to zero based
		movsx	ecx,word [esi+SYSTIME_Year] ; EBX <- year
SystemToJulian1:cmp	eax,byte 12	; is it valid value?
		jb	SystemToJulian3	; it is valid value
		or	eax,eax		; is month negative?
                jns	SystemToJulian2	; month is not negative
		add	eax,byte 12	; correct month
		dec	ecx		; correct year
		jmp	short SystemToJulian1 ; next year	

SystemToJulian2:sub	eax,byte 12	; correct month
		inc	ecx		; correct year
		jmp	short SystemToJulian1 ; next year

; ------------- Preset leap year flag (if year is divided by 4)

SystemToJulian3:push	eax		; push month (zero based)
		mov	bl,0		; BL <- 0, preset flag, no leap year
		test	cl,3		; is it leap year?
		jnz	SystemToJulia32	; it is not leap year
		inc	ebx		; BL <- 1, flag, it is leap year

; ------------- Check if it is Gregorian calendar (1600 and more)

SystemToJulia32:sub	ecx,1600	; is it Gregorian calendar?
		js	SystemToJulian6	; it is (mostly) Julian calendar
		cmp	ecx,3268-1600	; maximal year
		jb	SystemToJulian4	; year is OK
		mov	ecx,3268-1600	; limit year

; ------------- Get century (offset from 16th century)

SystemToJulian4:mov	eax,ecx		; EAX <- year
		mov	bh,100		; BH <- 100, years per century
		div	bh		; AL <- century, AH <- year in century

; ------------- Correct leap flag (century is leap if it is divided by 4)

		or	ah,ah		; is it century?
		jnz	SystemToJulia42	; it is not century
		test	al,3		; is century divided by 4?
		jz	SystemToJulia42	; century is divided by 4, leap year
		mov	bl,0		; BL <- 0, flag, not leap year

; ------------- Recalc year to days with Gregorian calendar

SystemToJulia42:mov	bh,ah		; BH <- year in century
		movzx	ecx,al		; ECX <- century - 16
		mov	eax,365		; EAX <- days in normal year
		movzx	edx,bh		; EDX <- year in century
		mul	edx		; EAX <- days for normal years
		add	eax,[Days1600+ecx*4] ; add days from 1/1/1600
		add	eax,2305448+10	; add days for 1/1/1600 + 10
		test	cl,3		; is century leap?
		movzx	ecx,bh		; ECX <- year in century
		jz	SystemToJulia64	; century is leap
		cmp	ecx,byte 3	; is it first quadrennium?
		jle	SystemToJulia66	; it is first quadrennium
		dec	ecx		; withou first (not leap) year
		jmp	short SystemToJulia65

; ------------- Recalc year to days with Julian calendar (or part of Gregorian)

SystemToJulian6:add	ecx,4712+1600	; change year to zero based
		jns	SystemToJulia62	; year is OK
		xor	ecx,ecx		; ECX <- 0, limit minimal year
SystemToJulia62:mov	eax,365		; EAX <- days to normal year
		mul	ecx		; EAX <- days for normal years
SystemToJulia64:add	ecx,byte 3	; round up
SystemToJulia65:shr	ecx,2		; ECX <- number of leap years
		add	eax,ecx		; add leap days
SystemToJulia66:pop	edx		; EDX <- pop month (zero based)

; ------------- Add days in months

		or	bl,bl		; is leap year?
		mov	ebx,DayYearTabN	; EBX <- table for normal year
		jz	SystemToJulian7	; it is normal year
		mov	ebx,DayYearTabL	; EBX <- table for leap year
SystemToJulian7:movzx	ecx,word [ebx+edx*2] ; ECX <- days for months
		add	eax,ecx		; add days for months

; ------------- Add days in month

		movsx	ecx,byte [esi+SYSTIME_Day] ; ECX <- day in month
		dec	ecx		; day correction
		add	eax,ecx		; add days to current date
		jns	SystemToJulian8	; date is OK
		xor	eax,eax		; EAX <- 0, minimal date

; ------------- Correction for date 11/1/1582 and more

SystemToJulian8:cmp	eax,2299171	; is it 10/15/1582 or more?
		jb	SystemToJulia82	; it is lower date
		sub	eax,byte 10	; date correction
SystemToJulia82:cmp	eax,2914673	; maximal date
		jbe	SystemToJulia84	; date is OK
		mov	eax,2914673	; limit maximal date

; ------------- Recalc days to minutes

SystemToJulia84:mov	ecx,24*60	; ECX <- minutes per day
		imul	ecx		; recalc days to minutes

; ------------- Recalc minutes to 100-nanoseconds

		xchg	eax,ebx		; EBX <- store minutes LOW
		xchg	eax,edx		; EAX <- minutes HIGH
		mov	ecx,60*10000000 ; ECX <- 100-nanoseconds per minute
		mul	ecx		; recalc minutes HIGH to 100-nanosec
		add	ebp,eax		; add minutes HIGH to accumulator HIGH
		xchg	eax,ebx		; EAX <- minutes LOW
		mul	ecx		; recalc minutes LOW to 100-nanosec
		add	eax,edi		; add accumulator LOW to minutes LOW
		adc	edx,ebp		; add accumulator HIGH to minutes LOW

; ------------- Limit result (maximal allowed value 2518277472000000000-1)

		jns	SystemToJulian9	; value is not negative
		xor	eax,eax		; EAX <- 0, minimal value LOW
		xor	edx,edx		; EDX <- 0, minimal value HIGH
SystemToJulian9:cmp	edx,22f2b804h	; check maximum HIGH
		jne	SystemToJulia92
		cmp	eax,0b46dbfffh	; check maximum LOW
SystemToJulia92:jbe	SystemToJulia94	; date is OK
		mov	edx,22f2b804h	; limit value HIGH
		mov	eax,0b46dbfffh	; limit value LOW
		        
; ------------- Pop registers

SystemToJulia94:pop	ebp		; pop EBP
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                     Convert Julian time to system time
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = Julian time (100-nanosec from 1/1/4713 BCE, noon)
;			must be in range from 0 to 2518277471999999999
;		EBX = system time structure (see SYSTIME)
; OUTPUT:	EBX structure filled with system time (only if NC)
;		CY = invalid range of Julian time, structure not filled
; NOTES:	Takes 800 ns on 1.6 GHz CPU.
; -----------------------------------------------------------------------------
; On whole function: ESI = system time structure

; ------------- Push registers

JulianToSystem:	push	eax		; push EAX
		push	ebx		; push EBX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI
		mov	esi,ebx		; ESI <- system time structure

; ------------- Check valid range (invalid value 2518277472000000000 and more)

		cmp	edx,22f2b804h	; check maximum HIGH
		jne	JulianToSystem1
		cmp	eax,0b46dc000h	; check maximum LOW
JulianToSystem1:cmc			; invert CF
		jc	near JulianToSystem9 ; invalid Julian time

; ------------- Split to minutes (-> EBX) and 100-nanoseconds (-> EDX)

		mov	ecx,60*10000000 ; ECX <- 100-nanoseconds per minute
		div	ecx		; split to minutes and 100-nanoseconds
		xchg	eax,ebx		; EBX <- minutes (0 to 4197129119)

; ------------- Get number of 100-nanoseconds and number of seconds

		xor	eax,eax		; EAX <- 0
		mov	[esi+SYSTIME_Flags],al ; clear flags
		xchg	eax,edx		; EAX <- 100-nanoseconds, EDX <- 0
		mov	ecx,10000000	; ECX <- 100-nanoseconds per second
		div	ecx		; get 100-nanoseconds and seconds
		mov	[esi+SYSTIME_100NSec],edx ; store 100-nanoseconds
		mov	[esi+SYSTIME_Sec],al ; store second

; ------------- Split to minutes (-> EAX) and days (-> EDX, 0 to 2914672)

		xchg	eax,ebx		; EAX <- minutes
		xor	edx,edx		; EDX <- 0
		mov	ecx,24*60	; ECX <- minutes per day
		div	ecx		; get minutes and days
		xchg	eax,edx		; EAX <- minutes, EDX <- days

; ------------- Get minute and hour (-> AL)

		mov	cl,60		; CL <- number of minutes per hour
		div	cl		; get number of minutes and hours
		mov	[esi+SYSTIME_Min],ah ; store minute

; ------------- Shift day over midnight

		add	al,12		; hour correction
		cmp	al,24		; is it midnight?
		jb	JulianToSystem2	; it is not midnight
		sub	al,24		; hour correction
		inc	edx		; day correction
JulianToSystem2:mov	[esi+SYSTIME_Hour],al ; store hour
		xchg	eax,edx		; EAX <- day

; ------------- Get day of week

		xor	edx,edx		; EDX <- 0
		mov	ebx,eax		; EBX <- push current day
		inc	eax		; day correction
		mov	cx,7		; ECX <- 7, number of days in week
		div	ecx		; get day of week
		mov	[esi+SYSTIME_DayWeek],dl ; store day of week

; ------------- Check if it is Gregorian calendar (=Julian date 2299160.5+0.5)

		xor	edx,edx		; EDX <- 0
		mov	eax,-4712	; EAX <- preset year correction
		xchg	eax,ebx		; EAX <- current day, EBX <- -4712
		cmp	eax,2299160+1	; is it Gregorian calendar?
		jb	JulianToSystem5	; it is Julian calendar
		or	byte [esi+SYSTIME_Flags],B1 ; flag - Gregorian calendar

; ------------- Years before 1/1/1600

		add	eax,byte 10	; date correction
		cmp	eax,2305447+1+10; is it 1/1/1600 or more?
		jb	JulianToSystem5	; calculate date as for Julian
		sub	eax,2305447+1+10; EAX <- day offset from 1/1/1600

; ------------- Get century (-> EAX, offset in century -> ECX)

		mov	ecx,eax		; ECX <- day offset from 1/1/1600
		shr	eax,15		; ECX <- index in hash table
		movzx	eax,byte [Days1600Hash+eax] ; ECX <- century
		cmp	ecx,[Days1600+eax*4-16*4] ; is it correct century?
		jae	JulianToSystem3	; century is OK
		dec	eax		; correct century
JulianToSystem3:sub	ecx,[Days1600+eax*4-16*4] ; ECX <- offset in century

; ------------- Recalc century to years (-> BX)

		mov	ebx,eax		; EBX <- century
		mov	ah,100		; AH <- 100, year per century
		mul	ah		; AX <- years for centuries
		xchg	eax,ebx		; BX <- years, EAX <- century

; ------------- Get first year in quadrennium (here is EDX = 0)

		xchg	eax,ecx		; EAX <- days, ECX <- century
		test	cl,3		; is it leap century?
		jz	JulianToSystem5	; it is leap century
		inc	eax		; add 1 leap day
		mov	ecx,3*365 + 366	; ECX <- days for quadrennium
		cmp	eax,ecx		; is first quadrennium?
		jae	JulianToSystem5	; it is not first quadrennium
		dec	eax		; return leap day
		mov	ecx,365		; ECX <- 365, days in first year
		xchg	eax,edx		; EDX <- days, EAX <- 0
		jmp	short JulianToSyst52

; ------------- Get quadrennium for Julian calendar (2299160 -> 1573 rest 1007)

JulianToSystem5:mov	ecx,3*365 + 366	; ECX <- days for quadrennium
		div	ecx		; calculate quadrennium
		shl	eax,2		; EAX <- years for quadrenniums

; ------------- Get years in last quadrennium

		mov	ecx,366		; ECX <- 366, days in a year
JulianToSyst52:	cmp	edx,ecx		; first year
		jb	JulianToSystem6	; it is first year
		sub	edx,ecx		; days in first year
		inc	eax		; increase year
		
		mov	cx,365		; ECX <- 365, days in a year
		cmp	edx,ecx		; first year
		jb	JulianToSystem6	; it is first year
		sub	edx,ecx		; days in first year
		inc	eax		; increase year

		cmp	edx,ecx		; first year
		jb	JulianToSystem6	; it is first year
		sub	edx,ecx		; days in first year
		inc	eax		; increase year

JulianToSystem6:add	ebx,eax 	; EBX <- store year

; ------------- Check leap year for Gregorian calendar

		test	byte [esi+SYSTIME_Flags],B1 ; is Gregorian calendar?
		jz	JulianToSyst64	; it is not Gregorian calendar
		mov	eax,ebx		; EAX <- year
		mov	cl,100		; CL <- 100 years per century
		div	cl		; get century
		or	ah,ah		; is it century?
		jnz	JulianToSyst64	; it is not century
		test	al,3		; is century leap (divided by 4) ?
		jnz	JulianToSystem7	; century is not leap

; ------------- Check leap year for Julian calendar (year divided with 4)

JulianToSyst64:	test	bl,3		; is year divided with 4?
		jnz	JulianToSystem7	; it is not leap year
JulianToSyst66:	or	byte [esi+SYSTIME_Flags],B0 ; flag - leap year

; ------------- Find month and day

JulianToSystem7:push	edx		; push EDX (day in year)
		mov	ecx,DayYearTabN	; days for normal year
		test	byte [esi+SYSTIME_Flags],B0 ; is leap year?
		jz	JulianToSyst72	; is normal year
		mov	ecx,DayYearTabL	; days for leap year
JulianToSyst72:	mov	eax,edx		; EAX <- day in year
		shr	eax,4		; EAX <- day in year / 16
		movzx	eax,byte [DayYearHash+eax] ; EAX <- month (hashed)
		cmp	dx,[ecx+eax*2-2]; is it correct month?
		jae	JulianToSyst74	; month is OK
		dec	eax		; correct month
JulianToSyst74:	sub	dx,[ecx+eax*2-2]; DX <- day in month
		mov	[esi+SYSTIME_Month],al ; store month
		inc	edx		; DL <- day + 1 correction
		mov	[esi+SYSTIME_Day],dl ; store day in month
		pop	edx		; pop EDX (day in year)

; ------------- Correction for 1582 year

		cmp	bx,1582		; is it 1582 year?
		jne	JulianToSystem8	; no
		cmp	edx,277		; is it day 10/15/1582 or more?
		jb	JulianToSystem8	; no correction
		sub	edx,byte 10	; restore right day number

; ------------- Store day in year

JulianToSystem8:mov	[esi+SYSTIME_DayYear],dx ; store day in year

; ------------- Store year

		mov	[esi+SYSTIME_Year],bx ; store year

; ------------- Prepare day of week of January 4th (-> BH)

		movzx	eax,byte [esi+SYSTIME_DayWeek] ; EAX <- day of week
		sub	eax,edx		; EAX <- day of week - day
		add	eax,3+53*7	; correction
		xor	ecx,ecx		; ECX <- 0
		mov	cl,7		; CL <- 7, days per week
		div	cl		; AH <- day of week of January 4th
		xchg	eax,ebx		; BH <- push day of week of January 4th

; ------------- Prepare number of weeks in this year

		mov	bl,52		; 52 weeks
		or	bh,bh		; is it Sunday?
		jz	JulianToSyst81	; this year has 53 weeks
		cmp	bh,6		; is it Saturday?
		jne	JulianToSyst82	; this year has 52 weeks
		test	byte [esi+SYSTIME_Flags],B0 ; is it leap year?
		jz	JulianToSyst82	; it is not leap year, it has 52 weeks
JulianToSyst81:	or	byte [esi+SYSTIME_Flags],B2 ; flags of 53 weeks
		inc	ebx		; BL <- 53 weeks

; ------------- Day offset (from begin of year) of first week (-> EAX)

JulianToSyst82:	mov	al,4		; AL <- day correction
		sub	al,bh		; AL <- day offset of first week
		movsx	eax,al		; EAX <- day offset of first week

; ------------- Get week (first week is week with January 4th, ISO-8601)

		xchg	eax,edx		; EAX <- day in year, EDX <- day offset
		sub	eax,edx		; EAX <- distance from first week
		add	eax,ecx		; EAX += 7, correction
		div	cl		; AL <- week

; ------------- Last week of previous year (only for January 1,2,3)

		or	al,al		; is it last week of previous year?
		jnz	JulianToSyst84	; it is not last week
		or	byte [esi+SYSTIME_Flags],B3 ; set flag of last week
		mov	cx,[esi+SYSTIME_Year] ; CX <- year
		mov	al,51		; week 51 for 1582 year
		cmp	cx,1583		; is it 1583 year?
		je	JulianToSyst84	; previous year has 51 weeks
		inc	eax		; AL <- week 52
		cmp	bh,1		; is January 4th in Monday?
		je	JulianToSyst83	; previous year has 53 weeks
		cmp	bh,2		; is January 4th in Tuesday?
		jne	JulianToSyst84	; previous year has 52 weeks
		dec	cx		; CX <- previous year
		test	cl,3		; is previous year leap?
		jnz	JulianToSyst84	; previous year is not leap, 52 weeks
		cmp	cx,1700		; not leap year
		je	JulianToSyst84	; it has 52 weeks
		cmp	cx,2100		; not leap year
		je	JulianToSyst84	; it has 52 weeks
		cmp	cx,2500		; not leap year
		je	JulianToSyst84	; it has 52 weeks
		cmp	cx,2900		; not leap year
		je	JulianToSyst84	; it has 52 weeks
JulianToSyst83:	inc	eax		; AL <- week 53

; ------------- First week of following year (1581 year is always OK)

JulianToSyst84:	cmp	al,bl		; is it valid week?
		jbe	JulianToSyst85	; it is valid week
		mov	al,1		; first week of next year
		or	byte [esi+SYSTIME_Flags],B4 ; first week of next year

; ------------- Store week

JulianToSyst85:	mov	[esi+SYSTIME_Week],al ; store week

; ------------- Pop registers

		clc			; result OK
JulianToSystem9:pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

; ------------- Days in month - normal year

DayMonthTabN:	db	31		; January
		db	28		; February
		db	31		; March
		db	30		; April
		db	31		; May
		db	30		; June
		db	31		; July
		db	31		; August
		db	30		; September
		db	31		; October
		db	30		; November
		db	31		; December

; ------------- Days in month - leap year

DayMonthTabL:	db	31		; January
		db	29		; February
		db	31		; March
		db	30		; April
		db	31		; May
		db	30		; June
		db	31		; July
		db	31		; August
		db	30		; September
		db	31		; October
		db	30		; November
		db	31		; December

; ------------- Days from begin of the normal year

		align	2, db 0
DayYearTabN:	dw	0				; (0)	January
		dw	31				; (31)	February
		dw	31+28				; (59)	March
		dw	31+28+31			; (90)	April
		dw	31+28+31+30			; (120)	May
		dw	31+28+31+30+31			; (151)	June
		dw	31+28+31+30+31+30		; (181)	July
		dw	31+28+31+30+31+30+31		; (212)	August
		dw	31+28+31+30+31+30+31+31		; (243)	September
		dw	31+28+31+30+31+30+31+31+30	; (273)	October
		dw	31+28+31+30+31+30+31+31+30+31	; (304)	November
		dw	31+28+31+30+31+30+31+31+30+31+30; (334)	December

; ------------- Days from begin of the leap year

		align	2, db 0
DayYearTabL:	dw	0				; (0)	January
		dw	31				; (31)	February
		dw	31+29				; (60)	March
		dw	31+29+31			; (91)	April
		dw	31+29+31+30			; (121)	May
		dw	31+29+31+30+31			; (152)	June
		dw	31+29+31+30+31+30		; (182)	July
		dw	31+29+31+30+31+30+31		; (213)	August
		dw	31+29+31+30+31+30+31+31		; (244)	September
		dw	31+29+31+30+31+30+31+31+30	; (274)	October
		dw	31+29+31+30+31+30+31+31+30+31	; (305)	November
		dw	31+29+31+30+31+30+31+31+30+31+30; (335)	December

; ------------- Hash table to quick find month (index = day >> 4, 0 to 22)

DayYearHash:	db	1				; 0 to 15: Jan
		db	2				; 16 to 31: Jan, Feb
		db	2				; 32 to 47: Feb
		db	3				; 48 to 63: Feb, Mar
		db	3				; 64 to 79: Mar
		db	4				; 80 to 95: Mar, Apr
		db	4				; 96 to 111: Apr
		db	5				; 112 to 127: Apr, May
		db	5				; 128 to 143: May
		db	6				; 144 to 159: May, Jun
		db	6				; 160 to 175: Jun
		db	7				; 176 to 191: Jun, Jul
		db	7				; 192 to 207: Jul
		db	8				; 208 to 223: Jul, Aug
		db	8				; 224 to 239: Aug
		db	9				; 240 to 255: Aug, Sep
		db	9				; 256 to 271: Sep
		db	10				; 272 to 287: Sep, Oct
		db	10				; 288 to 303: Oct
		db	11				; 304 to 319: Oct, Nov
		db	12				; 320 to 335: Nov, Dec
		db	12				; 336 to 351: Dec
		db	12				; 352 to 366: Dec

; ------------- Days from 1/1/1600

		align	4, db 0
Days1600:	dd	0				; 1/1/1600 (0)
		dd	100*365+25			; 1/1/1700 (36525)
		dd	200*365+25+24			; 1/1/1800 (73049)
		dd	300*365+25+2*24			; 1/1/1900 (109573)
		dd	400*365+25+3*24			; 1/1/2000 (146097)
		dd	500*365+2*25+3*24		; 1/1/2100 (182622)
		dd	600*365+2*25+4*24		; 1/1/2200 (219146)
		dd	700*365+2*25+5*24		; 1/1/2300 (255670)
		dd	800*365+2*25+6*24		; 1/1/2400 (292194)
		dd	900*365+3*25+6*24		; 1/1/2500 (328719)
		dd	1000*365+3*25+7*24		; 1/1/2600 (365243)
		dd	1100*365+3*25+8*24		; 1/1/2700 (401767)
		dd	1200*365+3*25+9*24		; 1/1/2800 (438291)
		dd	1300*365+4*25+9*24		; 1/1/2900 (474816)
		dd	1400*365+4*25+10*24		; 1/1/3000 (511340)
		dd	1500*365+4*25+11*24		; 1/1/3100 (547864)
		dd	1600*365+4*25+12*24		; 1/1/3200 (584388)

; ------------- Hash table to quick find century (index = day >> 15, 0 to 18)

Days1600Hash:	db	16				; 0..32767: 16
		db	17				; 32768..65535: 16,17
		db	18				; 65536..98303: 17,18
		db	19				; 98304..131071: 18,19
		db	20				; 131072..163839: 19,20
		db	21				; 163840..196607: 20,21
		db	22				; 196608..229375: 21,22
		db	23				; 229376..262143: 22,23
		db	24				; 262144..294911: 23,24
		db	24				; 294912..327679: 24
		db	25				; 327680..360447: 24,25
		db	26				; 360448..393215: 25,26
		db	27				; 393216..425983: 26,27
		db	28				; 425984..458751: 27,28
		db	29				; 458752..491519: 28,29
		db	30				; 491520..524287: 29,30
		db	31				; 524288..557056: 30,31
		db	32				; 557056..589823: 31,32
		db	32				; 589824..609226: 32

; -----------------------------------------------------------------------------
;                            Uninitialized data
; -----------------------------------------------------------------------------

		BSS_SECTION

Back to source browser