Загрузка
Английский
Польский
Домашняя страница Николая Гайдука

Библиотека календарных функций

О
сновной причиной создания библиотеки календарных функций (для календарей юлианского и григорианского) является мой интерес к истории, а особенно к античным временам. Кроме того, такая задача оказалась тоже очень занимательной с математической и программистич- ной точек зрения. Во-первых надо было создать математические модели всех календарных функций, во-вторых - перевести все эти теоретические формулы на язык ассемблера ФАСМ. В изначальном намерении календарные функции должны были обслуживать отрезок времени длиной сверх 11 миллионов лет начинающийся с 1 января 1 года н.э. (для юлианского календаря) и с 15 октября 1582 года (для григорианского календаря). Но многие интересные для историков события произошли как раз раньше начала нашей эры. Следовательно, надо было переделать календарные функции таким образом, чтоб обслуживали они отрезок времени идентичной длины, но с началом нашей эры расположенном почти в середине этого расстояния. Модифицированные календарные функции дают возможность использования дат предшествующих введению григорианского календаря и 1 января 1 года н.э. для юлианского календаря (так расширены календари зовут пролептическими), благодаря чему всякие конверсии дат между этими системами стали намного проще.

Для увеличения круга потенциальных пользователей описание библиотеки сделано на трёх языках (русском, английском и польском).

Возможности функций библиотеки

Библиотека календарных функций даёт программисту многие возможности:

  • обслуживает даты с периода длиной сверх 11 миллионов лет:
    • с 1 января 5843880 г. до н.э. по 3 августа 5915100 г. для юлианского календаря,
    • с 30 декабря 5844001 г. до н.э. по 17 января 5915222 г. для григорианского календаря,
  • свободная конверсия дат между календарями юлианском и григорианском в упомянутом периоде,
  • определение дня недели для данной даты,
  • вычисление номера дня в году для данных номеров месяца и дня в месяце,
  • определение високосности года в данном календаре,
  • вычисление "абсолютного" номера дня соответствующего данной дате, благодаря чему можно легко рассчитывать количество дней между двумя датами.

Краткое описание календарных функций

Библиотека содержит 8 функций для операций с датами:

  • DayOfWeek - рассчитывает для данной даты номер дня недели,
  • IsLeapYear - определяет високосность года в данном календаре,
  • MDToDayNum - рассчитывает порядковый номер дня в году (в зависимости от високосности года),
  • DayNumToMD - конвертирует данный номер дня в году в соответствующие номера месяца и дня в месяце,
  • DateToAbsDayNum - рассчитывает для данной даты соответствующий абсолютный номер дня,
  • AbsDayNumToDate - конвертирует абсолютный номер дня в соответствующую дату (в данном календаре),
  • GregorianToJulian - конвертирует григорианскую дату в соответствующую дату юлианского календаря,
  • JulianToGregorian - конвертирует юлианскую дату в соответствующую дату григорианского календаря.

Исходник

Ниже представлено содержание исходного файла библиотеки:

; Библиотека календарных функций написана на ассемблере ФАСМ.
;
; Возможности:
;	* обслуживает даты с периода длиной сверх 11 миллионов лет:
;		- с 1 января 5843880 г. до н.э. по 3 августа 5915100 г.
;		  для юлианского календаря,
;		- с 30 декабря 5844001 г. до н.э. по 17 января 5915222 г.
;		  для григорианского календаря,
;	* свободная конверсия дат между календарями юлианском и григорианском
;	  в упомянутом периоде,
;	* определение дня недели для данной даты,
;	* вычисление номера дня в году для данных номеров месяца и дня
;	  в месяце,
;	* определение високосности года в данном календаре,
;	* вычисление "абсолютного" номера дня соответствующего данной
;	  дате, благодаря чему можно легко рассчитывать количество дней
;	  между двумя датами.
;
; (C) Mikołaj Hajduk, 16.06.2008.
;
format PE GUI 4.0 DLL
entry DllEntryPoint

include 'win32a.inc'

; Определение используемых констант.
;
C1	= 365			; Количество дней в обычном году.

C4	= 4*C1 + 1		; Количество дней в четырёхлетнем цикле (основном  цикле юлианского календаря).

C100	= 25*C4 - 1		; Количество дней в "обычном" столетии григорианского календаря
				; (т.е. в столетии, которое заканчивается невисокосным годом).

C400	= 4*C100 + 1		; Количество дней в полном 400-летнем цикле григорианского календаря.

k	= 30

J	= 194796		; Константы, которые определяют количество полных лет календарей юлианского  
G	= 194800		; и григорианского содержимых в отрезке времени равном "Великому Циклу" T.


section '.data' data readable writeable

; Таблица, которая содержит длину месяцев обычного и високосного годов.
;
MonthLen	db 31,  28,  31,  30,  31,  30,  31,  31,  30,  31,  30,  31
		db 31,  29,  31,  30,  31,  30,  31,  31,  30,  31,  30,  31

; Таблица, которая содержит значения функции 'DaySum' для всех пар (номер месяца, флаг високосности года).
;
DaySum		dw  0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
		dw  0,  31,  60,  91, 121, 152, 182, 213, 244, 274, 305, 335


section '.code' code readable executable

proc	DllEntryPoint, hinstDLL, fdwReason, lpvReserved
	mov	eax, TRUE
	ret
endp

; DWORD DayOfWeek(DWORD Y, DWORD M, DWORD D, DWORD Gregorian)
;
; Функция рассчитывает для данной даты номер дня недели. Принято следующее определение: 0 - воскресенье, 
; 1 - понедельник, 2 - вторник, 3 - среда, 4 - четверг, 5 - пятница, 6 - суббота.
;
; Параметры:
;	Y - год,
;	M - месяц,
;	D - день,
;	Gregorian - определение календаря (0 - юлианский, 1 - григорианский).
;
; Возвращаемые значения:
;	* 0, 1, ..., 6, если дата верна,
;	* -1, если данные неверны.
;
proc	DayOfWeek, Y, M, D, Gregorian

	pushfd
	push	ebx edx

	stdcall DateToAbsDayNum, [Y], [M], [D], [Gregorian]		; eax := N
	test	eax, eax
	jz	.Error

	mov	ebx, 7							;
	xor	edx, edx						;
	add	eax, 5							; edx := (eax + 5) mod 7 = (N + 5) mod 7
	adc	edx, edx						;
	div	ebx							;

	xchg	eax, edx						; eax := edx
	jmp	.End

	.Error:
		mov	eax, -1
	.End:

	pop	edx ebx
	popfd

	ret
endp

; DWORD IsLeapYear(DWORD Y, DWORD Gregorian)
;
; Функция определяет високосность года в данном календаре.
;
; Параметры:
;	Y - год,
;	Gregorian - определение календаря (0 - юлианский, 1 - григорианский).
;
; Возвращаемые значения:
;	* 1, если год Y високосный, 0 - в противном случае.
;	* -1, если данные неверны.
;
proc	IsLeapYear, Y, Gregorian

	pushfd
	push	ebx edx

	.CheckParameters:
		test	[Gregorian], -2					; 0 <= Gregorian <= 1
		jnz	.Error						;

	.IsYNegative:
		mov	eax, [Y]					; eax := Y
		test	eax, eax
		jz	.Error
		jns	.CheckCalendar
									; eax < 0 (Y < 0)
									;
		inc	eax						; eax := eax + 1
		neg	eax						; eax := -eax = -(Y + 1) = -Y - 1 =
									;      = |Y| - [Y < 0] = Y'

	.CheckCalendar:
		cmp	[Gregorian], 0
		je	.mod4

	.Gregorian:
		xor	edx, edx					; eax := E(eax / 100) = E(Y' / 100)
		mov	ebx, 100					; edx := eax mod 100 = Y' mod 100
		div	ebx						; 

		test	edx, edx
		jz	.mod4

		mov	eax, edx					; eax := edx = Y' mod 100
									; 
									; {(Y' mod 100) mod 4 = Y' mod 4} 

	.mod4:
		shr	eax, 1						; eax := E(eax / 2); CF := eax mod 2
		jc	.Result						; 

		shr	eax, 1						; eax := E(eax / 2); CF := eax mod 2
		jmp	.Result						;

	.Error:
		mov	eax, -1
		jmp	.End

	.Result:
		setnc	al						; eax := not CF
		movzx	eax, al						;

	.End:

	pop	edx ebx
	popfd

	ret
endp

; DWORD MDToDayNum(DWORD M, DWORD D, DWORD LeapYearFlag)
;
; Функция рассчитывает порядковый номер дня в году (в зависимости от високосности года).
;
; Параметры:
;	M - месяц,
;	D - день,
;	LeapYearFlag - флаг високосности года (0 - год нормальный, 1 - високосный).
;
; Возвращаемые значения:
;	* 1, 2, ..., 365 для нормального года, 1, 2, ..., 366 для високосного года,
;	* -1, если данные неверны.
;
proc	MDToDayNum, M, D, LeapYearFlag

	pushfd
	push	ebx edx

	.LeapYearFlag:
		test	[LeapYearFlag], -2				; 0 <= LeapYearFlag <= 1
		jnz	.Error						;

	.Month:
		cmp	[M], 1						;
		jb	.Error						; 1 <= M <= 12
		cmp	[M], 12						;
		ja	.Error						;

	.Day:
		cmp	[D], 1						; D >= 1
		jb	.Error						;

		mov	ebx, [LeapYearFlag]				; ebx := LeapYearFlag
		lea	ebx, [ebx + 2*ebx]				; ebx := 3*ebx = 3*LeapYearFlag
		shl	ebx, 2						; ebx := 4*ebx = 12*LeapYearFlag

		mov	edx, [M]					; eax := MonthLen[M - 1 + 12*LeapYearFlag]
		movzx	eax, [MonthLen - 1 + ebx + edx]			;

		cmp	[D], eax					; D <= MonthLen[M - 1 + 12*LeapYearFlag]
		ja	.Error						;

	.CalculateDayNum:
		shl	ebx, 1						; ebx := 2*ebx = 24*LeapYearFlag
		movzx	eax, [DaySum - 2 + ebx + 2*edx]			; eax := DaySum(M, LeapYearFlag)
		add	eax, [D]					; eax := eax + D = DaySum(M, LeapYearFlag) + D 
		jmp	.End

	.Error:
		mov	eax, -1

	.End:

	pop	edx ebx
	popfd

	ret
endp

; DWORD DayNumToMD(DWORD n, DWORD LeapYearFlag, DWORD* M, DWORD* D)
;
; Функция конвертирует данный номер дня в году в соответствующие номера месяца и дня в месяце.
; Результат сильно зависит от значения флаги високосности года.
;
; Параметры:
;	n - номер дня в году,
;	LeapYearFlag - флаг високосности года (0 - год нормальный, 1 - високосный),
;	M - указатель на переменную в которую будет записан вычисленный номер месяца,
;	D - указатель на переменную в которую будет записан вычисленный номер дня. 
;
; Возвращаемые значения:
;	* 0, если данные верны (n, LeapYearFlag),
;	* -1 в противном случае.
;
proc	DayNumToMD, n, LeapYearFlag, M, D

	pushfd
	push	ebx ecx edx

	.CheckParameters:
		test	[LeapYearFlag], -2				; 0 <= LeapYearFlag <= 1
		jnz	.Error

		cmp	[n], 1						; n >= 1
		jb	.Error						;

		mov	eax, 365					;
		add	eax, [LeapYearFlag]				; eax := 365 + LeapYearFlag
		cmp	[n], eax					; n <= eax
		ja	.Error						;

	.CalculateMD:
		mov	ebx, [LeapYearFlag]				; ebx := LeapYearFlag
		lea	ebx, [ebx + 2*ebx]				; ebx := 3*ebx = 3*LeapYearFlag
		shl	ebx, 3						; ebx := 8*ebx = 24*LeapYearFlag

		mov	ecx, 12						;
									;
		.Loop:							; ecx := max{i; 1 <= i <= 12, DaySum(i, LeapYearFlag) < n} = m
			movzx	edx, [DaySum - 2 + ebx + 2*ecx]		;
			cmp	[n], edx				; edx := DaySum(m, LeapYearFlag)
			ja	.LoopEnd				;
			loop	.Loop					;

		.LoopEnd:
			mov	eax, [M]				; M := ecx = m
			mov	[eax], ecx				;

			mov	ecx, [n]				; ecx := n
			sub	ecx, edx				; ecx := ecx - edx = n - DaySum(m, LeapYearFlag)

			mov	eax, [D]				; D := ecx
			mov	[eax], ecx				;

			xor	eax, eax

			jmp	.End

	.Error:
		mov	eax, -1

	.End:

	pop	edx ecx ebx
	popfd

	ret
endp

; DWORD DateToAbsDayNum(DWORD Y, DWORD M, DWORD D, DWORD Gregorian)
;
; Функция рассчитывает для данной даты соответствующий абсолютный номер дня.
;
; Параметры:
;	Y - год,
;	M - месяц,
;	D - день,
;	Gregorian - определение календаря (0 - юлианский, 1 - григорианский).
;
; Возвращаемые значения:
;	* 1, 2, ..., 2^32-1, если дата данного календаря верна,
;	* 0, если данные неверны.
;
proc	DateToAbsDayNum, Y, M, D, Gregorian

	pushfd
	push	ebx ecx edx

	test	[Gregorian], -2						; 0 <= Gregorian <= 1
	jnz	.Error							;

	stdcall	IsLeapYear, [Y], [Gregorian]				;
	cmp	eax, -1							; eax := IsLeapYear(Y, Gregorian)
	je	.Error							;

									; Y <> 0

	mov	ebx, eax						; ebx := eax

	stdcall	MDToDayNum, [M], [D], ebx				;
	cmp	eax, -1							; eax := MDToDayNum(M, D, ebx) = n
	je	.Error							;

	mov	ecx, [Y]						;
	cmp	ecx, 0							; ecx := Y
	jg	.CalculateDayNum					;

	inc	ecx							; Y < 0
									; ecx := ecx + 1 = Y + 1 = Y + [Y < 0]

	.CalculateDayNum:
		add	ecx, k*J					; 
		cmp	[Gregorian], 0					; ecx := ecx + kJ + k(G-J)[Gregorian = 1] =
		je	.Yprim0						;      = Y + [Y < 0] + kJ + k(G-J)[Gregorian = 1] = Y'
		add	ecx, k*(G-J)					; 

	.Yprim0:
		cmp	ecx, 0						;
		jne	.YprimPositive					; Y' = 0
		sub	eax, 364					; eax := eax - 364 = n - 364
		jmp	.End						;

	.YprimPositive:							; Y' > 0
									;
		dec	ecx						; ecx := ecx - 1 = Y' - 1
		mov	ebx, eax					; ebx := eax = n

		mov	eax, 365					; eax := 365
		mul	ecx						; eax := 365 * ecx = 365(Y' - 1)
		
		shr	ecx, 2						; ecx := E(ecx / 4) = E((Y' - 1) / 4)
		add	eax, ecx					; eax := eax + ecx = 365(Y' - 1) + E((Y' - 1) / 4)
		add	eax, ebx					; eax := eax + ebx = eax + n =
									;      = 365(Y' - 1) + E((Y' - 1) / 4) + n

		cmp	[Gregorian], 0
		jz	.End

	.Gregorian:
		push	eax						; X := eax

		xor	edx, edx					;
		mov	eax, ecx					; eax := ecx = E((Y' - 1) / 4)
		mov	ebx, 25						;
		div	ebx						; eax := E(eax / 25) = E(E((Y' - 1) / 4) / 25) =
									;      = E((Y' - 1) / 100)

		mov	ecx, eax					; ecx := eax = E((Y' - 1) / 100)
		pop	eax						; eax := X = 365(Y' - 1) + E((Y' - 1) / 4) + n

		sub	eax, ecx					; eax := eax - ecx = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                    - E((Y' - 1) / 100)

		shr	ecx, 2						; ecx : = E(ecx / 4) = E(E((Y' - 1) / 100) / 4) =
									;       = E((Y' - 1) / 400)


		add	eax, ecx					; eax := eax + ecx = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                    - E((Y' - 1) / 100) + E((Y' - 1) / 400)

		add	eax, 2						; eax := eax + 2 = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                  - E((Y' - 1) / 100) + E((Y' - 1) / 400) + 2 =
									;                = N

		jmp	.End

	.Error:
		xor	eax, eax

	.End:

	pop	edx ecx ebx
	popfd

	ret
endp

; DWORD AbsDayNumToDate(DWORD N, DWORD Gregorian, DWORD* Y, DWORD* M, DWORD* D)
;
; Функция конвертирует абсолютный номер дня N = 1, 2, ..., 2^32-1 в соответствующую дату (в данном календаре).
;
; Параметры:
;	N - абсолютный номер дня,
;	Gregorian - определение календаря (0 - юлианский, 1 - григорианский),
;	Y - указатель на переменную в которую будет записан вычисленный номер года,
;	M - указатель на переменную в которую будет записан вычисленный номер месяца,
;	D - указатель на переменную в которую будет записан вычисленный номер дня.
;
; Возвращаемые значения:
;	* 0, если данные верны (N, Gregorian),
;	* -1 в противном случае.
;
proc	AbsDayNumToDate, N, Gregorian, Y, M, D

	pushfd
	push	ebx ecx edx

	cmp	[N], 0							; N <> 0
	je	.Error							;

	test	[Gregorian], -2						; 0 <= Gregorian <= 1
	jnz	.Error							;

	xor	ecx, ecx						; ecx := 0
	
	mov	eax, [N]						; eax := N - 1
	dec	eax							;

	cmp	[Gregorian], 0
	je	.Julian

	.Gregorian:
		cmp	eax, 1
		ja	.NextDays

									; 0 <= eax <= 1 (1 <= N <= 2)

		mov	ebx, [M]					; M := 12
		mov	dword [ebx], 12					;

		add	eax, 30						; eax := eax + 30 = N - 1 + 30 = N + 29 

		mov	ebx, [D]					; D := eax = N + 29
		mov	[ebx], eax					;

		mov	ecx, -k*G - 1					; ecx := -kG - 1

		jmp	.ReturnY

	.NextDays:							; eax > 1 (N > 2)

		sub	eax, 2						; eax := eax - 2 = N - 1 - 2 = N - 3

		xor	edx, edx					;
		mov	ebx, C400					; eax := E(eax / C400) = E((N - 3) / C400)
		div	ebx						; edx := eax mod C400 = (N - 3) mod C400

		lea	eax, [eax + 4*eax]				; eax := 5*eax = 5*E((N - 3) / C400)
		lea	eax, [eax + 4*eax]				; eax := 5*eax = 5*(5*E((N - 3) / C400)) =
									;              = 25*E((N - 3) / C400)

		shl	eax, 4						; eax := 16*eax = 16*(25*E((N - 3) / C400)) =
									;               = 400*E((N - 3) / C400)

		xchg	ecx, eax					; ecx := eax = 400*E((N - 3) / C400)
									; 

		xchg	eax, edx					; eax := edx = (N - 3) mod C400
									; 

		.Centuries:						;
			cmp	eax, C100				;
			jb	.Julian					;
									;
			add	ecx, 100				;
			sub	eax, C100				;
									;
			cmp	eax, C100				; (eax, ecx) := P(eax, ecx) = 
			jb	.Julian					;             = P((N - 3) mod C400, 400*E((N - 3) / C400)) =
									;             = (N100, Y100)
			add	ecx, 100				;
			sub	eax, C100				;
									;
			cmp	eax, C100				;
			jb	.Julian					;
									;
			add	ecx, 100				;
			sub	eax, C100				;

	.Julian:
									;                             /
									;                             |  (N - 1, 0)                                 ; Gregorian = 0
									; (N100, Y100) = (eax, ecx) = <
									;                             |  P((N - 3) mod C400, 400*E((N - 3) / C400)) ; Gregorian = 1
									;                             \

		xor	edx, edx					;
		mov	ebx, C4						; eax := E(eax / C4) = E(N100 / C4)
		div	ebx						; edx := eax mod C4 = N100 mod C4

		shl	eax, 2						; eax := 4*eax = 4*E(N100 / C4)

		add	ecx, eax					; ecx := ecx + eax = Y100 + 4*E(N100 / C4)

		.Years:							;
			inc	ecx					;
			cmp	edx, C1					;
			jb	.MD					;
									;
			sub	edx, C1					;
									;
			inc	ecx					; (edx, ecx) := Q(edx, ecx) =
			cmp	edx, C1					;             = Q(N100 mod C4, Y100 + 4*E(N100 / C4)) =
			jb	.MD					;             = (N', Y*)
									;
			sub	edx, C1					;
									;
			inc	ecx					;
			cmp	edx, C1					;
			jb	.MD					;
									;
			sub	edx, C1					;
									;
			inc	ecx					;

	.MD:
		inc	edx						; edx := edx + 1 = N' + 1

		stdcall	IsLeapYear, ecx, [Gregorian]			; eax := IsLeapYear(ecx, Gregorian) =
									;      = IsLeapYear(Y*, Gregorian)

		stdcall	DayNumToMD, edx, eax, [M], [D]			; eax := DayNumToMD(edx, eax, M, D) =
									;      = DayNumToMD(N' + 1, IsLeapYear(Y*, Gregorian), M, D)

		cmp	[Gregorian], 0
		je	.JulianYears

		.GregorianYears:					;
			sub	ecx, k*(G - J)				;
									; ecx := ecx - kJ - k(G - J)[Gregorian = 1] =
		.JulianYears:						;      = Y* - kJ - k(G - J)[Gregorian = 1] = 
			sub	ecx, k*J				;      = Y'

			cmp	ecx, 0
			jg	.ReturnY
									; ecx <= 0 (Y' <= 0)

			dec	ecx					; ecx := ecx - 1 = Y' - 1 = Y' - [Y' <= 0]

		.ReturnY:
			mov	eax, [Y]				; Y := ecx
			mov	[eax], ecx				;

		xor	eax, eax
		jmp	.End

	.Error:
		mov	eax, -1

	.End:

	pop	edx ecx ebx
	popfd

	ret
endp

; DWORD GregorianToJulian(DWORD Yg, DWORD Mg, DWORD Dg, DWORD* Yj, DWORD* Mj, DWORD* Dj)
;
; Функция конвертирует григорианскую дату в соответствующую дату юлианского календаря.
;
; Параметры:
;	Yg - год григорианской даты,
;	Mg - месяц григорианской даты,
;	Dg - день григорианской даты,
;	Yj - указатель на переменную в которую будет записан вычисленный номер года юлианской даты,
;	Mj - указатель на переменную в которую будет записан вычисленный номер месяца юлианской даты,
;	Dj - указатель на переменную в которую будет записан вычисленный номер дня юлианской даты.
;
; Возвращаемые значения:
;	* 0, если григорианская дата верна,
;	* -1 в противном случае.
;
proc	GregorianToJulian, Yg, Mg, Dg, Yj, Mj, Dj

	.GregorianToNum:
		stdcall DateToAbsDayNum, [Yg], [Mg], [Dg], 1
		test	eax, eax
		jz	.Error

	.NumToJulian:
		stdcall AbsDayNumToDate, eax, 0, [Yj], [Mj], [Dj]
		jmp	.End

	.Error:
		mov	eax, -1

	.End:

	ret
endp

; DWORD JulianToGregorian(DWORD Yj, DWORD Mj, DWORD Dj, DWORD* Yg, DWORD* Mg, DWORD* Dg)
;
; Функция конвертирует юлианскую дату в соответствующую дату григорианского календаря.
;
; Параметры:
;	Yj - год юлианской даты,
;	Mj - месяц юлианской даты,
;	Dj - день юлианской даты,
;	Yg - указатель на переменную в которую будет записан вычисленный номер года григорианской даты,
;	Mg - указатель на переменную в которую будет записан вычисленный номер месяца григорианской даты,
;	Dg - указатель на переменную в которую будет записан вычисленный номер дня григорианской даты.
;
; Возвращаемые значения:
;	* 0, если юлианская дата верна,
;	* -1 в противном случае.
;
proc	JulianToGregorian, Yj, Mj, Dj, Yg, Mg, Dg

	.JulianToNum:
		stdcall DateToAbsDayNum, [Yj], [Mj], [Dj], 0
		test	eax, eax
		jz	.Error

	.NumToGregorian:
		stdcall AbsDayNumToDate, eax, 1, [Yg], [Mg], [Dg]
		jmp	.End

	.Error:
		mov	eax, -1

	.End:

	ret
endp


section '.edata' export data readable

	export	'Calendar.dll',\
		AbsDayNumToDate,	'AbsDayNumToDate',\
		DateToAbsDayNum,	'DateToAbsDayNum',\
		DayNumToMD,		'DayNumToMD',\
		DayOfWeek,		'DayOfWeek',\
		GregorianToJulian,	'GregorianToJulian',\
		IsLeapYear,		'IsLeapYear',\
		JulianToGregorian,	'JulianToGregorian',\
		MDToDayNum,		'MDToDayNum'


section '.reloc' fixups data discardable

© 2007-2014, Mikołaj Hajduk