Also:
unsigned months_to_days (unsigned int month) { return (month * 3057 - 3007) / 100; }
http://www.snippets.org/snippets/SCALDATE.C
Conversion of Units of Measure
Jim Hartmann says:
Normally, a clock frequency that is a power of 2 is used (for example 3.2768MHz). However, there is a method using fixed point fractions where you can get precise real time with *any* stabile crystal frequency. The beauty of it is that you can use the same method for any crystal and you can even calibrate your crystal for more precision.Example:
- Crystal frequency is 3.1416 Mhz. (pi Mhz)
- Timer divisor is 65536.
- Timer rollover at 3.1416Mhz/4/65536 = 11.9843 hz.
- I want 5ppm accuracy per second (long term).
- I would like to increment my real time clock at 1 second intervals.
Therefore:
- Every timer rollover I need to add 1/11.9843 to my one second counter.
- At 5ppm per second I need 5E-6/11.9843 or .417E-6 precision on my fraction.
- The number of bits needed is abs(log(precision)/log(2)). abs(log(.417E-6)/log(2)) = 21.19. 22 bits will give greater than 5ppm precision.
- Calculate my fixed point fraction constant : (1/11.9843) * 2^22 ~= 349983. In other words 1/11.9843 = 349983/ 2^22. At every timer overflow, I add 349983 to my 22 bit fraction accumulator. We need 3 bytes of ram to store this fraction. When a '1' appears in bit 22, one second has elapsed and I can increment my real time and clear bit 22. The first overflow will occur after 12 additions, but on average the overflows will occur every 11.9843 additions.
Its easier to see the effect when the constant is in hex,
349983 = 0x5571FFor my example here is the first 14 iterations of the clock:
Iteration Accumulator 0 000000 1 05571F 2 0AAE3E 3 10055D 4 155C7C 5 1AB39B 6 200ABA 7 2561D9 8 2AB9F8 9 301017 10 356736 11 3ABE55 12 401574 (overflow into bit 22, 1 second elapsed, clear bit 22) 13 056C93For more precision, add more bits to the fraction. To tweek it for your crystal's tolerance, adjust the LSB of the fraction.
...this algorithm is really the same as a "phase accumulator" with 22 bit precision and a 1 second period.
Andrew Warren says:
Want to mentally calculate the day of the week for any month, day, and year?Here's how:
Just remember that, in any given year, the following nine dates all fall on the same day of the week:
4/4 These should be easy to remember 6/6 8/8 10/10 7/11 These can be remembered by the mnemonic, "I work at the 7-11, from 9 to 5." 11/7 9/5 5/9 last day of February Either the 28th or 29th, depending In 1998, those nine dates all fall on Saturday. Every year, this day advances by one, unless the year is a leap year, in which case it advances by two.
That is... These nine dates will all fall on Sunday in 1999, on Tuesday in 2000 (because 2000 is a leap year), on Wednesday in 2001, on Thursday in 2002, etc.
Now... If someone asks you, "Quick! What day is August 2, 1999?", you'd think, "Hmm... 8/8 is a Saturday this year, so it'll be a Sunday next year, and six days before that would be, umm...", and answer "Monday!"
With a little practice, you'll find that you can come up with the day of the week in just a few seconds, for any date within a few years of today.
Since you know that the day of the week advances by five days every four years, you can easily calculate the day-of-the-week for years further in the past and future, too.
The only thing you'll have to remember, if you're asked to prove that you're some sort of Rainman-esque idiot savant by calculating the day of the week for dates in other centuries, is that century years are only leap years if they're divisible by 400. That is, 2000 is a leap year, but 1700, 1800, 1900, and 2100 aren't.
That last bit is complicated, so if it were me, I'd answer those "Rainman" challenges with: "What do you think I am... An idiot savant or something?"
See also:
Archive: