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

Obsah / Utility / CALENDAR / Inkrementace a dekrementace data

Zdrojový kód: INCLUDE\UTIL\CALENDAR.INC, UTIL\CALENDAR.ASM


Inkrementace a dekrementace data


; -----------------------------------------------------------------------------
;                       Increase date-time by one day
; -----------------------------------------------------------------------------
; INPUT:	EBX = date-time structure (see DATETIME)
; OUTPUT:	CY = invalid date (structure has not been changed)
; NOTES:	Date entries are verified only partially.
; -----------------------------------------------------------------------------

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

DateTimeAddDay:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Increase day in month

		mov	eax,[ebx+DATETIME_Date] ; EAX <- date
		inc	eax		; increase day in month
		cmp	eax,(SPLITYEAR*256 + 10)*256 + 5 ; date 10/5/1582
		setne	dl		; DL <- 0=date 10/5/1582, 1=not
		dec	edx		; DL <- 0ffh=date 10/5/1582, 0=not
		and	dl,10		; DL <- 10=date 10/5/1582, 0=not
		add	al,dl		; date correction for 10/5/1582
		cmp	al,28		; maximal date we need not to check
		jbe	DateTimeAddDay6	; new date is OK

; ------------- Check day in month

		shld	ecx,eax,16	; CX <- year
		xchg	al,ah		; AL <- month, AH <- day in month
		xchg	eax,edx		; DL <- month, DH <- day in month
		call	GetLastDayMonth	; get last day in month -> AL
		xchg	eax,edx		; AL <- month, AH <- day, DL<-last day
		xchg	al,ah		; AL <- day in month, AH <- month
		jc	DateTimeAddDay8	; invalid month or year
		cmp	al,dl		; check day in month
		jbe	DateTimeAddDay6	; new day is OK

; ------------- Increase month

		mov	al,1		; AL <- 1, first day in next month
		inc	ah		; AH <- next month
		cmp	ah,12		; check month
		jbe	DateTimeAddDay6	; next month is OK

; ------------- Increase year

		mov	ah,1		; AH <- 1, first month in next year
		inc	ecx		; increase year
		cmp	cx,MAXYEAR	; maximal year
		stc			; set error flag
		jg	DateTimeAddDay8	; invalid year
		add	eax,10000h	; increase year
		
; ------------- Set new date

DateTimeAddDay6:mov	[ebx+DATETIME_Date],eax ; store new date
		clc			; clear error flag

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

DateTimeAddDay8:pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Pomocí funkce DateTimeAddDay je možné zvýšit datum ve struktuře DATETIME o jeden den. Ukazatel na strukturu DATETIME je funkci předán v registru EBX. Funkce mění pouze položky den v měsíci, měsíc a rok, ostatní položky (např. den v týdnu) zůstávají neovlivněny. Funkce provádí pouze nejnutnější testy platnosti položek. Při chybě navrátí nastavený chybový příznak CF a obsah struktury DATETIME zůstane nezměněn. Jsou-li potřebné i rozšiřující informace o datu, je možné dodatečně zavolat funkci DateTimeExt.

Funkce nejdříve načte datum ze struktury DATETIME. Pokud se jedná o speciální případ 5.10.1582, zvýší se den v měsíci o 10 dnů, jinak se zvýší o 1 den. Pro den v měsíci 28 nebo nižší není potřeba dělat další obsluhu a funkce se ukončí.

Pro den 29 a vyšší je nutné provést test přetečení data do dalšího měsíce. Pomocí funkce GetLastDayMonth se zjistí číslo posledního dne v měsíci a porovnáním se zjistí, zda den v měsíci přetekl do dalšího měsíce. Pokud ano, nastaví se den v měsíci na 1 a zvýší se číslo měsíce.

Pokud měsíc přetekl přes hodnotu 12, nastaví se měsíc na hodnotu 1 a zvýší se číslo roku. Pokud by i rok přetekl přes povolenou maximální hodnotu, funkce navrátí nastavený příznak chyby CF a datum ve struktuře se nezmění. Při úspěšné operaci se uloží nová hodnota data do struktury DATETIME.


; -----------------------------------------------------------------------------
;                       Decrease date-time by one day
; -----------------------------------------------------------------------------
; INPUT:	EBX = date-time structure (see DATETIME)
; OUTPUT:	CY = invalid date (structure has not been changed)
; NOTES:	Date entries are verified only partially.
; -----------------------------------------------------------------------------

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

DateTimeSubDay:	push	eax		; push EAX
		push	edx		; push EDX

; ------------- Decrease day in month

		mov	eax,[ebx+DATETIME_Date] ; EAX <- date
		cmp	eax,(SPLITYEAR*256 + 10)*256 + 15 ; date 10/15/1582
		setne	dl		; DL <- 0=date 10/15/1582, 1=not
		dec	edx		; DL <- 0ffh=date 10/15/1582, 0=not
		and	dl,10		; DL <- 10=date 10/15/1582, 0=not
		inc	edx		; DL <- correction + 1 day
		sub	al,dl		; decrease day in month
		jnz	DateTimeSubDay6	; new date is OK

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

		push	ecx		; push ECX

; ------------- Decrease month

		shld	ecx,eax,16	; CX <- year
		dec	ah		; decrease month
		jnz	DateTimeSubDay2	; new month is OK

; ------------- Decrease year

		dec	ecx		; decrease year
		sub	eax,0F400h	; decrease year, set month to 12

; ------------- Get last day in previous month

DateTimeSubDay2:mov	dl,ah		; DL <- month
		call	GetLastDayMonth	; get last day in month -> AL

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

		pop	ecx		; pop ECX
		jc	DateTimeSubDay8	; invalid month or year

; ------------- Set new date

DateTimeSubDay6:mov	[ebx+DATETIME_Date],eax ; store new date
		clc			; clear error flag

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

DateTimeSubDay8:pop	edx		; pop EDX
		pop	eax		; pop EAX
		ret

Pomocí funkce DateTimeSubDay je možné snížit datum ve struktuře DATETIME o jeden den. Ukazatel na strukturu DATETIME je funkci předán v registru EBX. Funkce mění pouze položky den v měsíci, měsíc a rok, ostatní položky (např. den v týdnu) zůstávají neovlivněny. Funkce provádí pouze nejnutnější testy platnosti položek. Při chybě navrátí nastavený chybový příznak CF a obsah struktury DATETIME zůstane nezměněn. Jsou-li potřebné i rozšiřující informace o datu, je možné dodatečně zavolat funkci DateTimeExt.

Funkce nejdříve načte datum ze struktury DATETIME. Pokud se jedná o speciální případ 15.10.1582, sníží se den v měsíci o 10 dnů, jinak se sníží o 1 den. Pokud den v měsíci nedosáhl hodnoty nula, nedošlo k přetečení do předešlého měsíce a funkce se ukončí.

Při dosažení dne 0 se do registru ECX připraví číslo roku a sníží se číslo měsíce. Pokud měsíc dosáhl hodnoty 0, dochází k přetečení do předešlého roku. V tom případě se sníží číslo roku a měsíc se nastaví na hodnotu 12.

Pomocí funkce GetLastDayMonth se zjistí číslo posledního dne v předešlém měsíci a toto číslo se stane novým dnem v měsíci. Pokud funkce nevrátí chybový kód (indikující neplatný rok nebo měsíc), uloží se nové datum a funkce se ukončí. Při chybě se funkce ukončí bez změny struktury DATETIME.


Obsah / Utility / CALENDAR / Inkrementace a dekrementace data