Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
except in century years, like 2000, take the 4 digit year value and divide by 4, if no reminder, then a leap yearHey,
What is a simple way to detect a leap year?
i mean in code.
I'm writing an application in C language and am not sure how to do it in a simple way.
Thanks.
;******************************************************************
;* *
;* Day_of_Week, 2000-2099 Mike McLaren, K8LH, Aug '07 *
;* *
;* preset: Month (1..12), Day (1..31), Year (0..99) vars' *
;* return: W = 0..6 (Sun..Sat) *
;* *
;* 39 words, 1 local variable (14 bit core) *
;******************************************************************
radix dec
;
; char Month; // 1..12
; char Day; // 1..31
; char Year; // 0..99 (2000-2099)
;
; char DayOfWeek() // Mike McLaren, K8LH, Aug '07
; { // returns 0..6 (Sun..Sat)
; char Leap;
; const rom char Base[] = { 5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3 };
; Leap = (Year & 3) || (Month > 2);
; return (Base[Month-1] + Day + Leap + Year + Year/4) % 7;
; }
;
DayOfWeek
clrf Leap ; Leap = 0 |B0
movf Month,W ; get Month (1..12) |B0
addlw -3 ; C = 0 if Jan or Feb |B0
movf Year,W ; W = Year (0..99) |B0
andlw b'00000011' ; is this a leap year? |B0
skpz ; yes, skip, else |B0
setc ; set C (force Leap = 1) |B0
rlf Leap,F ; Leap = 0 or 1 |B0
;
; an "in-line table" of DOW values minus 1 for the 1st of each
; month in 2000, a leap year. 1st param is desired value, 2nd
; param cancels out WREG, and 3rd param cancels out next table
; entry. an "in-line" table saves me 1 word and 1 stack level
; but uses more cycles for lower table index values. the "in-
; line table" is 256-byte-boundary tolerant.
;
; WREG = Y2000[Month-1]
;
movlw high (Y2000) ; |B0
movwf PCLATH ; |B0
decf Month,W ; |B0
addlw low (Y2000) ; |B0
skpnc ; |B0
incf PCLATH,F ; |B0
movwf PCL ; |B0
Y2000 xorlw 5^$^(1^$+1) ; 6 (Jan 2000) |B0
xorlw 1^$^(1^$+1) ; 2 (Feb) |B0
xorlw 1^$^(4^$+1) ; 2 (Mar) |B0
xorlw 4^$^(6^$+1) ; 5 (Apr) |B0
xorlw 6^$^(2^$+1) ; 0 (May) |B0
xorlw 2^$^(4^$+1) ; 3 (Jun) |B0
xorlw 4^$^(0^$+1) ; 5 (Jul) |B0
xorlw 0^$^(3^$+1) ; 1 (Aug) |B0
xorlw 3^$^(5^$+1) ; 4 (Sep) |B0
xorlw 5^$^(1^$+1) ; 6 (Oct) |B0
xorlw 1^$^(3^$+1) ; 2 (Nov) |B0
xorlw 3^$ ; 4 (Dec) |B0
;
; WREG = (((Y2000[Month-1]+Day+Leap)*2 + Year/2)/2 + Year) % 7
;
addwf Day,W ; add Day (1..31) |B0
addwf Leap,F ; add Leap (0 or 1), C=0 |B0
rlf Leap,F ; multiply by 2, C=0 |B0
rrf Year,W ; divide year by 2 |B0
addwf Leap,F ; add 'em together, C=0 |B0
rrf Leap,W ; divide result by 2 |B0
addwf Year,W ; add Year (0..99) |B0
Mod7 addlw -7 ; result % 7 |B0
bc Mod7 ; |B0
addlw 7 ; |B0
return ; W = 0..6 (Sun..Sat) |B0
;
I use a similar method. In the comments below, when year & 3 == 0 it's a leap year...
Regards, Mike
Code:;****************************************************************** ;* * ;* Day_of_Week, 2000-2099 Mike McLaren, K8LH, Aug '07 * ;* * ;* preset: Month (1..12), Day (1..31), Year (0..99) vars' * ;* return: W = 0..6 (Sun..Sat) * ;* * ;* 39 words, 1 local variable (14 bit core) * ;****************************************************************** radix dec ; ; char Month; // 1..12 ; char Day; // 1..31 ; char Year; // 0..99 (2000-2099) ; ; char DayOfWeek() // Mike McLaren, K8LH, Aug '07 ; { // returns 0..6 (Sun..Sat) ; char Leap; ; const rom char Base[] = { 5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3 }; ; Leap = (Year & 3) || (Month > 2); ; return (Base[Month-1] + Day + Leap + Year + Year/4) % 7; ; } ; DayOfWeek clrf Leap ; Leap = 0 |B0 movf Month,W ; get Month (1..12) |B0 addlw -3 ; C = 0 if Jan or Feb |B0 movf Year,W ; W = Year (0..99) |B0 andlw b'00000011' ; is this a leap year? |B0 skpz ; yes, skip, else |B0 setc ; set C (force Leap = 1) |B0 rlf Leap,F ; Leap = 0 or 1 |B0 ; ; an "in-line table" of DOW values minus 1 for the 1st of each ; month in 2000, a leap year. 1st param is desired value, 2nd ; param cancels out WREG, and 3rd param cancels out next table ; entry. an "in-line" table saves me 1 word and 1 stack level ; but uses more cycles for lower table index values. the "in- ; line table" is 256-byte-boundary tolerant. ; ; WREG = Y2000[Month-1] ; movlw high (Y2000) ; |B0 movwf PCLATH ; |B0 decf Month,W ; |B0 addlw low (Y2000) ; |B0 skpnc ; |B0 incf PCLATH,F ; |B0 movwf PCL ; |B0 Y2000 xorlw 5^$^(1^$+1) ; 6 (Jan 2000) |B0 xorlw 1^$^(1^$+1) ; 2 (Feb) |B0 xorlw 1^$^(4^$+1) ; 2 (Mar) |B0 xorlw 4^$^(6^$+1) ; 5 (Apr) |B0 xorlw 6^$^(2^$+1) ; 0 (May) |B0 xorlw 2^$^(4^$+1) ; 3 (Jun) |B0 xorlw 4^$^(0^$+1) ; 5 (Jul) |B0 xorlw 0^$^(3^$+1) ; 1 (Aug) |B0 xorlw 3^$^(5^$+1) ; 4 (Sep) |B0 xorlw 5^$^(1^$+1) ; 6 (Oct) |B0 xorlw 1^$^(3^$+1) ; 2 (Nov) |B0 xorlw 3^$ ; 4 (Dec) |B0 ; ; WREG = (((Y2000[Month-1]+Day+Leap)*2 + Year/2)/2 + Year) % 7 ; addwf Day,W ; add Day (1..31) |B0 addwf Leap,F ; add Leap (0 or 1), C=0 |B0 rlf Leap,F ; multiply by 2, C=0 |B0 rrf Year,W ; divide year by 2 |B0 addwf Leap,F ; add 'em together, C=0 |B0 rrf Leap,W ; divide result by 2 |B0 addwf Year,W ; add Year (0..99) |B0 Mod7 addlw -7 ; result % 7 |B0 bc Mod7 ; |B0 addlw 7 ; |B0 return ; W = 0..6 (Sun..Sat) |B0 ;
if integer(year/4)=year/4 then
if integer(year/100)!=year/100 then
DoLeapYear()
else
if integer(year/400)=year/400 then
DoLeapYear()
end if
end if
end if