[Back to DATETIME SWAG index]  [Back to Main SWAG index]  [Original]

(* Public domain

Author: Marius Ellen, Winsum, Groningen, The Netherlands
Fido 2:282/607.2

 After studying several DayOfWeeks i got sick.
 None of them worked really correctly and most
 had over 15 DIV'/MOD's or * in it.
 The Zeller's congruence was the best but the
 routine also contains some range errors. Years
 are only valid from 1..6300 and its really slow,
 so i wrote my own..


 About the routines..
 routine results valid if year in 0..65536
 month in 1..12, and day in 1..28/29/30/31
 there is absolute no range checking..
*)

function DayOfWeek(year,month,day:word):word;
{Returns the day of week, 0=Sun..6=Sat}
assembler; {See 1995}
const mtable:array[0..11] of byte=
  (0,3, 3,6, 1,4, 6,2, 5,0, 3,5);
asm
{(Y+(Y div 4)-(Y div 100)+(Y div 400)-Adjust)mod 7}
        mov    ax,year
        mov    di,ax
        xor    bx,bx
        xor    cx,cx
        mov    si,day
        dec    si
        shr    ax,1; adc cl,0 {si+=year div 4}
        shr    ax,1; adc cl,0
        add    si,ax
        mov    bx,25          {si+=year div 100}
        xor    dx,dx
        div    bx
        sub    si,ax
        shr    ax,1; adc ch,0 {si+=year div 400}
        shr    ax,1; adc ch,0
        add    si,ax
        add    si,di
{if leap-year then decrease days}
        mov    bx,month
        cmp    bx,2;  ja  @Noleap {do not adjust}
        and    cl,cl; jne @NoLeap {year mod 4=0?}
        and    dx,dx; jne @IsLeap {year mod 100=0?}
        and    di,di; je  @NoLeap {year=0?}
        and    ch,ch; jne @Noleap {year mod 400=0?}
@IsLeap:dec    si
@Noleap:xor    ah,ah
        mov    al,byte ptr mTable[bx-1]
        add    ax,si
        mov    bx,7
        xor    dx,dx
        div    bx
        xchg   ax,dx
end;

function GetDaysInMonth(Month:Byte;Year:Word):Word;
{Returns the total number of days in a month}
assembler;
asm
        mov    bl,Month
        {What about februari?}
        cmp    bl,2; jne @N
        mov    ax,Year
        shr    ax,1; jc @S
        shr    ax,1; jc @S
        {it's a leap-year}
        mov    cx,25; div cx
        and    dx,dx; jne @T
        {its a century}
        and    al,3;  jne @S
    @T: {leap}
        mov    ax,29; jmp @E
    @S: {noleap}
        mov    ax,28; jmp @E
    @N: {Nope, calc moth day's}
        mov    ax,15
        shr    bl,1; rcl ax,1
        cmp    bl,4; jb @E
        xor    ax,1
    @E:
end;

function GetDaysInYear(Year:Word):Word;
{Returns the total number of days in a year}
assembler;
asm
        mov    ax,2
        push   ax
        push   year
        call   GetDaysInMonth
        add    ax,(365-28)
end;


[Back to DATETIME SWAG index]  [Back to Main SWAG index]  [Original]