Puzzled with Time Server conversion problems?

Bill Eldridge bill at hk.rfa.org
Wed Oct 6 07:32:31 EDT 1999


Malcolm Tredinnick wrote:
> def calc_leap_years(year):
>         if (year > 1900):
>                 return ((year - 1900) - 1)/4
>         else:
>                 return 0
> 
> Of course, you can reduce it to a single line if you make the
> assumption that the year will always be greater than 1900. And it
> probably isn't wonderful programming practice to return 0 if say
> year==1897 anyway (raise an exception?), but that is another issue.
> This should be a fair bit faster than looping through the years.

Researching this:
------------------------------
Years devisabl by 4 ARE leap years
Except years devisable by 100 are NOT leap years
Except years devisable by 400 which ARE leap years
Except years devisable by 4000 which are NOT leap years!
------------------------------
I thought there was a third rule in addition to %100 & %400 for
millenia.

def calc_leap_years(year):
        if (1900 < year < 2101):
                return (year - 1901)/4
	else if (2100 < year):
		return (year - 1901)/4 -(year-2001)/100 +
(date-2001)/400)-(date-2001)/4000
	else if year==1900:
                return 0
	else:
		return -1

Note that the most common cases come first in the if/else - move 1900 up
if that's
of interest.  Of course there were also seconds added to the clock
between 1900 and
now (and between 1970 and now), and these would have to be manually
added.

def leapyear(year):
	return ( (not (year % 4)) and (year % 100)) or ( (not (year % 400)) and
(year % 4000) ) )
        #temp = ((year % 4 == 0) and (year % 100 <>0)) or (year % 400 
== 0)
        #return temp



It's quite possible for speed that you would even make a dictionary for
1900-2101.

Then you have:

leapyears={1900:0,1901:0,1902:0,...2100:0,2101:1}
calcleapyears={1900:0,1901:0,1902:0...2100:49,2101:49}

def calc_leap_years(year):
	if calcleapyears.haskey(year):
		return leapyears[year]
	else if (2100 < year):
		return (year - 1901)/4 -(year-2001)/100 +
(date-2001)/400)-(date-2001)/4000
	else:
		return -1

def leapyear(year):
	if leapyears.haskey(year):
		return leapyears[year]
	else:
		return ( (not (year % 4)) and (year % 100)) or ( (not (year % 400))
and (year % 4000) ) )

or use a "try except" if that improves speed.  If you're sure you only
need years
1900-2101, you can skip the functions completely, and just use the
dictionaries in
your code instead of function calls.

------------------------------------------------------------------

# Move 1-time calculations out of functions
secs_per_day    = 86400.0	#24.0*60*60    # 86400
secs_per_year   = 31536000.0	#365.0 * secs_per_day
leapyear        = 1896          # (1880, 1884, 1888, 1892, 
1896, 1904, 1908)
secs_to_1970 = 2209161600.0	#  70.0*365*24*3600 + 19.0*24*3600	# 19, not
18, leap years

def timeserver_calculation():

	return long(time.time() + secs_to_1970)



--
Bill Eldridge
Radio Free Asia
bill at hk.rfa.org




More information about the Python-list mailing list