Proton BASIC Compiler - New Article

• # Work with Calendars and Dates

The Gregorian Calendar is the internationally used one, it was proposed by Aloysius Lilius, and adopted by Pope Gregory XIII in 1582 to correct for errors in the older Julian Calendar which was introduced by Julius Caesar in 45 BC.

The Julian calendar introduces an error of 1 day every 128 years, to remedy this, 10 days has been dropped from October 1582 so that 15 October is follow immediately after 4 October, and from then on the Gregorian Calendar is used.

Great Britain (including USA) adopted the Gregorian calendar such that 2 Sep 1752 was followed by 14 Sep 1752.

The Gregorian Calendar is based on 400 years cycle (146097 Days, giving a year of average length 365.2425 days) , the common year is 365 days and the leap year is 366 days.

Leap years are determined according to the following rule:

Every year that is exactly divisible by 4 is a leap year, except for years that are exactly divisible by 100; these centurial years are leap years only if they are exactly divisible by 400.

Years, 2004,2008, 2012 are leap years, years 2100,2200,2300 are common years, and years 2000, 2400, 2800 are leap years.

The attached Proton + code uses the above rules to calculate the following:

Total Number of days with reference to 1/1/1 Gregorian, it can be used to calculate the days difference between two dates. Week of the day Check date validity Check leap year Calculate maximum days per a specific month. Generates a monthly calendar displayed on GLCD. The code is based on commented subroutines, so you can modify it as per your needs.

A final word, the Gregorian calendar will slip one day every about 3300 years, This could be corrected by dropping one leap year from the Gregorian calendar every 4000 years, which would make years divisible by 4000 non-leap years. But this is not adopted yet. Live and see!

'Calendar.Bas

'The Gregorian calendar is based on 400 years cycle
'The common year is 365 days and the leap year is 366 days.
'Every year that is exactly divisible by 4 is a leap year,
'Every year that is exactly divisible by 100 is a common year,
'Every year that is exactly divisible by 400 is a leap year,

Include "proton_G4.int" ' Or Your board setting
'Device 16f628
'xtal = 4

Dim Year as word ' Year variable
Dim Month as byte ' Month variable
Dim Day as byte ' Day variable

Dim Date_Status as bit ' 0 Invalid , 1 Valid date

Dim Complete_Years as dword ' Complete years count \should be word
' dword is used because of anomaly in v2.2.3
Dim Complete_4_Years_Cycles as word ' Complete 4 years cycles count
Dim Complete_100_Years_Cycles as byte ' Complete 100 years cycles count
Dim Complete_400_Years_Cycles as byte ' Complete 400 years cycles count
Dim Complete_Years_Days as dword ' Complete years days count
Dim Complete_Months_Days as word ' Current year complete months days count
Dim Total_Days as dword ' Total days count

Dim Leap_Years as word ' Leap years count
Dim Current_Year_leap as bit ' 0 common year, 1 leap year

Dim Day_OF_Week as byte ' SUN,MON,TUS,WED,THI,FRI,SAT [0,1,2,3,4,5,6]

Dim Month_Max_Days as byte ' Maximum days per the specified month

Dim Row as byte
Dim Col as byte

Dim Temp as byte ' Temperory variable

Goto Main ' Jump over subroutines

'************************************************* ***************
' ******************** CHECK DATE VALIDITY *******************

' Input Variables : Year, Month, Day
' Internal Variables: -
' Output Varaibles : Date_Status
' Used Subroutines : Get_Month_Max_Days (Check_Leap)

Check_Date:

Date_Status =0 ' Set to invalid
If Year > 0 Then ' Check Year
If Month > 0 Then ' Check Month
If Month < 13 Then ' Check Month
Gosub Get_Month_Max_Days ' Get month max days
If Day > 0 then ' Check Day
If Day <= Month_Max_Days Then Date_Status = 1 ' Check Day, set to valid if passed
Endif
Endif
Endif
Endif
Return

'************************************************* ***************
' ************** Get the month maximum days ******************

' Input Variables : Month
' Internal Variables: -
' Output Variables : Month_Max_Days
' Used Subroutines : Check_Leap

Get_Month_Max_Days:

Month_Max_Days = Lookup Month,[0,31,28,31,30,31,30,31,31,30,31,30,31] ' Get month maximum Days
' Use Lookupl if your PICŪ and code need it
If Month = 2 then ' Check if month 2
Gosub Check_Leap ' Check if Leap Year
Month_Max_Days = Month_Max_Days + Current_Year_leap ' Adjust for leap year
End if

Return

'************************************************* ***************
' *********** Check if current year is a leap year ***********

' Input Variables : Year
' Internal Variables: -
' Output Variables : Current_Year_leap
' Used Subroutines : -

Check_Leap:

Current_Year_leap = 0 ' =0 common year, =1 leap year
If Year//4 = 0 then Current_Year_leap=1 ' it is leap year
If Year//100 = 0 then Current_Year_leap=0 ' It is common year
If Year//400 = 0 then Current_Year_leap=1 ' It is leap year

Return

'************************************************* ***************
' ******** DATE DAYS CALCULATION REFERENCED TO 1/1/1 *********

' Input Variables : Year, Month, Day
' Internal Variables: Complete_Years, Complete_4_Years_Cycles, Complete_100_Years_Cycles
' Complete_400_Years_Cycles, Leap_Years, Complete_Years_Days
' Complete_Months_Days,
' Output Variables : Total_Days, Day_OF_Week
' Used Subroutines : Check_Leap

Calc_Days:

Total_Days=0

' Calculate total days of all complete years ( current year is excluded)

Complete_Years = Year - 1 ' Complete years count
Complete_4_Years_Cycles = Complete_Years/4 ' Leap years
Complete_100_Years_Cycles = Complete_Years/100 ' Not leap years
Complete_400_Years_Cycles = Complete_Years/400 ' Leap years
Leap_Years = Complete_4_Years_Cycles - Complete_100_Years_Cycles + Complete_400_Years_Cycles
Complete_Years_Days = Complete_Years * 365 + Leap_Years

' Calculate total days of the current year complete months

Branch Month,[BRA_EXIT,JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,N OV,DECM] ' branch to get complete months days count
' Use Branchl if your PICŪ and code need it
JAN:
Complete_Months_Days = 0 ' No complete month
Goto BRA_EXIT
FEB:
Complete_Months_Days = 31 ' Completed months are 1
Goto BRA_EXIT
MAR:
Complete_Months_Days = 59 ' (28 days for month 2), Completed months are 1,2
Goto BRA_EXIT
APR:
Complete_Months_Days = 90 ' Completed months are 1,2,3
Goto BRA_EXIT
MAY:
Complete_Months_Days = 120 ' Completed months are 1,2,3,4
Goto BRA_EXIT
JUN:
Complete_Months_Days = 151 ' Completed months are 1,2,3,4,5
Goto BRA_EXIT
JUL:
Complete_Months_Days = 181 ' Completed months are 1,2,3,4,5,6
Goto BRA_EXIT
AUG:
Complete_Months_Days = 212 ' Completed months are 1,2,3,4,5,6,7
Goto BRA_EXIT
SEP:
Complete_Months_Days = 243 ' Completed months are 1,2,3,4,5,6,7,8
Goto BRA_EXIT
OCT:
Complete_Months_Days = 273 ' Completed months are 1,2,3,4,5,6,7,8,9
Goto BRA_EXIT
NOV:
Complete_Months_Days = 304 ' Completed months are 1,2,3,4,5,6,7,8,9,10
Goto BRA_EXIT
DECM:
Complete_Months_Days = 334 ' Completed months are 1,2,3,4,5,6,7,8,9,10,11
Goto BRA_EXIT
BRA_EXIT:

If Month > 2 then ' Only if month > 2
Gosub Check_Leap ' Check if leap year
Complete_Months_Days = Complete_Months_Days + Current_Year_leap ' adjust for leap year if any
Endif
Total_Days = Complete_Years_Days + Complete_Months_Days + Day ' Sum all days
Day_OF_Week =Total_Days//7 ' SUN,MON,TUS,WED,THI,FRI,SAT [0,1,2,3,4,5,6]

Return

'************************************************* ***************
' **************** Monthly Calendar Generator ****************

' Input Variables : Year, Month,Day
' Internal Variables: -
' Output Varaibles : Calender
' Used Subroutines : Check_Date, Calc_Days

Make_Calender:
Cls ' clear GLCD
Temp= Day ' Keep current day
Day = 1 ' Set day to day 1 of the month
Gosub Check_Date ' Check date validity
If Date_Status=0 Then Gosub Date_InValid
Gosub Calc_Days ' get Day_OF_Week and Month_Max_Days
Print at 0,8,inverse 0, dec month,"/",dec year ' Print calendar title
Print at 1,0,Inverse 1, " S M T W T F S " ' Print calendar header

Row = 2 ' start at row 2

Print_Calender:
Col = Day_OF_Week*3+1 ' Point to col. position

If Day=Temp then ' Check if current day
Print at row,col,Inverse 1, Dec day ' Print current day
Else
Print at row,col,Inverse 0, Dec day ' Print day
EndIF

Inc Day ' Next day
If day > Month_Max_Days then goto Exit_Print_calendar ' Exit if month end
Inc Day_OF_Week ' Next day of week
If Day_OF_Week > 6 then ' Check day of week range
Day_OF_Week = 0 ' Reset day of week
Inc row ' Point to next row
End if
goto Print_Calender ' Loop
Exit_Print_calendar:

Return

'************************************************* ***************
' ***************** INVALID DATE HANDLER ********************

Date_InValid:
' Do what you want
Print at 1,1,"InValid Date"
stop

Return

'************************************************* ***************
' *********************** MAIN CODE *************************
Main:

Year=2004 ' Current Year
Month=3 ' Current Month
Day=15 ' Current Day

'Gosub Check_Date ' Activate to Check date validity
'If Date_Status=0 Then Gosub Date_InValid ' Make you decision
'Gosub Calc_Days ' Activate to calculate date days and day of week

'Print at 1,1, Dec Total_Days
'Print at 2,1, Dec Day_OF_Week

Gosub Make_Calender

End
Include "Font.inc" ' Use GLCD Font
contributed by Mohammed Tayem.