Tweaking our computation of the interval between two moments in time

Date:April 15, 2005 / year-entry #94
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20050415-52/?p=35893
Comments:    6
Summary:We can take our computation of the interval between two moments in time and combine it with the trick we developed for using the powers of mathematics to simplify multi-level comparisons to reduce the amount of work we impose upon the time/date engine. static void PrintAge(DateTime bday, DateTime asof) { // Accumulate years without going...

We can take our computation of the interval between two moments in time and combine it with the trick we developed for using the powers of mathematics to simplify multi-level comparisons to reduce the amount of work we impose upon the time/date engine.

static void PrintAge(DateTime bday, DateTime asof)
{
 // Accumulate years without going over.
 int years = asof.Year - bday.Year;
 if (asof.Month*32 + asof.Day < bday.Month*32 + bday.Day) years--;
 DateTime t = bday.AddYears(years);

 // Accumulate months without going over.
 int months = asof.Month - bday.Month;
 if (asof.Day < bday.Day) months--;
 months = (months + 12) % 12;
 t = t.AddMonths(months);

 // Days are constant-length, woo-hoo!
 int days = (asof - t).Days;

 SC.WriteLine("{0} years, {1} months, {2} days",
              years, months, days);
}

Observe that we avoided a call to the AddYears method (which is presumably rather complicated because years are variable-length) by replacing it with a multi-level comparison to determine whether the ending month/day falls later in the year than the starting month/day. Since no month has 32 days, a multiplier of 32 is enough to avoid an overflow of the day into the month field of the comparison key.


Comments (6)
  1. df says:

    // Days are constant-length, woo-hoo!

    Because of leap-seconds this is not entirely accurate.

    There is a known law of software that anything to do with dates and times is suspect.

  2. Jonathan Payne says:

    Does anything in Windows take account of leap seconds? If I used an embedded version of Windows for my time machine and wanted to go back to 1601, should I pass the time machine the number of nano-seconds in the FILETIME structure for the current time or should I add on a few more for leap seconds? I hope Microsoft isn’t ignoring the market for time machine operating systems.

  3. Norman Diamond says:

    This has been discussed before. Posix-compatible systems are required to have time-of-day clocks that are already incorrect by around 20 seconds, and Windows systems are compatible with that whether or not their Posix subsystems are being used.

    The part I can’t figure out is why, after a Windows system uses NTP to nearly synchronize itself with an atomic clock (after two or three intermediaries), how come it doesn’t adjust itself to 20 seconds in the future. Also what happens to a Posix system if it happens to execute an NTP operation during a leap second.

  4. Merle says:

    That’s a neat trick. Took me a few sample cases to see that it really worked, but neat. Could be very useful in environments like SQL Server, where the datediff() methods are way too basic: the year datediff() just subtracts the years, ignoring month and day.

    I would, of course, expect a *much* better comment in the source code than the one you provided.

    And, err, you didn’t avoid a call to AddYears(). Maybe you meant some other method?

    One other question: how does .net handle daylight savings time? I recall having to do brutal hacks to get past the fact that IE6.0 ignored DST, but 6.0a suddenly became the *only* browser to automatically adjust datetimes to reflect DST. (meaning the timeless date arithmetic I was trying to perform lost or gained a day after rounding).

  5. Ben Hutchings says:

    Norman: NTP has a flag that the time server can use to warn that a leap second is coming up. Typical NTP clients on POSIX systems make the clock run a bit slow for a few minutes before and after that time, so the leap second is never visible.

  6. mousic says:

    More math?

    static void PrintAge(DateTime bday, DateTime asof)

    {

    int diffSortOf = 32*(asof.Month + 12*asof.Year) + asof.Day

    – 32*(bday.Month + 12*bday.Year) – bday.Day;

    int years = diffSortOf/32/12;

    int months = (diffSortOf % (32*12)) / 32;

    DateTime t = bday.AddYears(years).AddMonths(months);

    int days = (asof – t).Days;

    SC.WriteLine( "{0} years, {1} months, {2} days"

    , years, months, days);

    }

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index