0

i have one question on setting on date, mon and year. we know that every 4 year February is equal to 29 days and the rest is 28 days. So i'm try to code something to let the program know which year of February is equal to 28 or 29 days.

Below is my code what i'm trying to ask is, is there any more simple and short method to do it?

void Timer(void) interrupt 1
{
if(start_timer == 1)
{
TF0 = 0;
TH0 = 0xB1;
TL0 = 0XE0;
msec++;

if(msec==100)
{
    sec++;
    msec=0;
}
if(sec==60)
{
    min++;
    sec=0;          
}
if(min==60)
{
    hour++;
    min=0;  
}
if(hour==24)
{
    date++;
    hour=0;
}
if(date== 30 && mon == 2 ( && year == 2016 || year == 2020 || year == 2024 ))
{
    mon++;
    date=1;
}
if(date== 29 && mon == 2 ( && year == 2015 || year == 2017 || year == 2018 || year == 2019|| year == 2021 || year == 2022 || year == 2023))
{
    mon++;
    date=1;
}
if(date==32 ( && mon == 1 || mon == 3 || mon == 5 || mon == 7 || mon == 9 || mon == 11))
{
    mon++;
    date=1;
}
if(date==31 ( && mon == 4 || mon == 6 || mon == 8 || mon == 10 || mon == 12))
{
    mon++;
    date=1;
}
if(mon==13)
{
    sec = 0;
    min = 0;
    hour = 0;
    date = 1;
    mon = 1;
    year = year++;
}
}
}

Updated:

void Timer(void) interrupt 1 {
    static const int daymon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int daysinmon, leapyear;
    if (start_timer == 1) {
        TF0 = 0;
        TH0 = 0xB1;
        TL0 = 0XE0;
        msec++;
        if (msec >= 100)   {              
            msec -= 100;
            if (++sec >= 60) {
                sec -= 60;          
                if (++min >= 60) {
                    min -= 60;  
                    if (++hour >= 24) {     
                        hour -= 24;
                        daysinmon = daymon[mon-1];
                        if (mon == 2) {     // months 1-based
                            if (year % 4 == 0)
                                leapyear = 1;
                            else if (year % 100 != 0)
                                leapyear = 0;
                            else if (year % 400 == 0)
                                leapyear = 1;
                            else leapyear = 0;

                            if (leapyear == 1)
                                daysinmon++;
                        }

                        if (++date > daysinmon) {
                            date = 1;                 // days 1-based
                            if (++mon > 12) {
                                mon = 1;
                                year++;
                            }
                        }
                    }
                }
            }
        }
    }
}
Fufu Alex
  • 37
  • 1
  • 1
  • 9

4 Answers4

1

Possibly you want the generic rule of determining the leap year. See this page

To determine whether a year is a leap year, follow these steps:
1.If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5
2.If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
3.If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
4.The year is a leap year (it has 366 days).
5.The year is not a leap year (it has 365 days).

The code generic way to determine a leap year can be

uint8 leapYearTest(uint16 year) {
if ( year % 4 == 0)
    {if ( year % 100 == 0)
        if (year % 400 == 0)
            return true;
    }
else
    return false; 
return false;
}

The above code can be shorten into one line as

if ( (year%400==0)|| ((year%4==0) && (year%100!=0)))
    return true;
else
    return false;

Then you can increment the date based on the result of the function return.

if (mon==2)
{
     date = (date+1)%(leapYearTest(year)+28);
}

I suspect that the algorithm can be done with pre-processing.

HarryQ
  • 1,281
  • 2
  • 10
  • 25
1

You have given the interrupt handler far too much work to do, checking everything at every interrupt. I have made some other changes too, not perhaps necessary but more robust, to check the adjustment when each element wraps. A future modification to the code might see the interrupt function interrupt itself, or be delayed by higher priority interrupts.

EDIT The date and the month are now 1-based to save confusion.

void Timer(void) interrupt 1 {
    static const int daymon[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int daysinmon, leapyear;
    if (start_timer == 1) {
        TF0 = 0;
        TH0 = 0xB1;
        TL0 = 0XE0;
    msec++;
    // and now you could re-enable interrupts to make it re-entrant
    if (msec >= 1000)   {               // altered to 1000, and the conditional test
        msec -= 1000;
        if (++sec >= 60) {
            sec -= 60;          
            if (++min >= 60) {
                min -= 60;  
                if (++hour >= 24) {     // the last time we adjust rather than zero
                    hour -= 24;
                    daysinmon = daymon [mon];
                    if (mon == 2) {
                        if (year % 400 == 0)
                            leapyear = 1;
                        else if (year % 100 == 0)
                            leapyear = 0;
                        else if (year % 4 == 0)
                            leapyear = 1;
                        else leapyear = 0;
                        if (leapyear)
                            daysinmon++;
                    }
                    if (++date > daysinmon) {
                        date = 1;
                        if (++mon > 12) {
                            mon = 1;
                            year++;
                        }
                    }
                }
            }
        }
    }

Sample test output:

27  2 2000
28  2 2000
29  2 2000
 1  3 2000
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • I tried your code above, only the February not changed. What i did was, i set date = 28, mon = 2, year =2015. 23:59:59. When the timer hit 00:00:00, it increase the date to 29 – Fufu Alex Feb 11 '15 at 04:35
  • just to check with you, when i set 28-2-2000. the next increment should be 29-2-2000 but it change to 01-03-2000 – Fufu Alex Feb 11 '15 at 10:23
  • That is because I made the month and the date both zero-based. You could change `if (++date >= daysinmon) { date = 0; ...` to `if (++date > daysinmon) { date = 1; ...` – Weather Vane Feb 11 '15 at 11:26
  • Did you also change the `>=` to `>` ? I compiled this as a test function called once from a `main()` and I found it works testing 27-1-2000 which was a leap year. It rolled to 28-1-2000 (zero based) and then to 0-2-2000 – Weather Vane Feb 11 '15 at 14:11
  • Oh oh! i make a changes in `>=` to `>` Yes is working now. Thanks. I appreciate the help – Fufu Alex Feb 11 '15 at 14:20
  • And now I changed the answer to be 1-based for day and month, sorry for the confusion. – Weather Vane Feb 11 '15 at 14:20
0

Perhaps if ((year-2000)%4==0) would be slightly more future proof

edit: yes slightly because it will fail in 2100 but that will be somebody else's problem.

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
0

For leap years

if ((year & 3) == 0) ...

For non-leap years

if ((year & 3) != 0) ...

Edit:

& is a bitwise and. In binary

0000 & 0011 = 0000
0001 & 0011 = 0001
0010 & 0011 = 0010
0011 & 0011 = 0011
0100 & 0011 = 0000

When a number is divisible by 4, a bitwise and with 3 will result in 0. You don't need to worry about 2100, 2200 or 2300 unless you expect your hardware to be used well into the next few centuries.

cup
  • 7,589
  • 4
  • 19
  • 42