0

With regards to this thread, I've developed a partial solution:

function strtosecs($time,$now=null){
    static $LEAPDIFF=86400;
    $time=strtotime($time,$now);
    return $time-(round((date('Y',$time)-1968)/4)*$LEAPDIFF);
}

The function is supposed to get the number of seconds given a string without checking leap-years.

It does this calculating the number of leap-years 1970 [(year-1986)/4], multiplying it by the difference in seconds between a leap-year and a normal year (which in the end, it's just the number of seconds in a day).

Finally, I simply remove all those excess leap-year seconds from the calculated time. Here's some examples of the inputs/outputs:

// test code
echo strtosecs('+20 years',0).'=>'.(strtosecs('+20 years',0)/31536000);
echo strtosecs('+1 years',0).'=>'.(strtosecs('+1 years',0)/31536000);

// test output
630676800 => 19.998630136986
31471200  => 0.99794520547945

You will probably ask why am I doing a division on the output? It's to test it out; 31536000 is the number of seconds in a year, so that 19.99... should be 20 and 0.99... should be a 1. Sure, I could round it all and get "correct" answer, but I'm worried about the inaccuracies.

Edit1: Since it doesn't seem obvious, my problem is with inveteracies; you just don't ask PHP for 20 years and it gives you 19.99..., right?

Edit2: It all seems to boil down to the part about 1968;

  • 1970; found it accurate in all tests I've tried.
  • 1969; Found it used here (...ex: (2008-1969)/4 = 9.75...) as well as mentioned here. Accurate after the 2nd year (+3 years) onwards.
  • 1968; as detailed below, this is "year zero" of leap years from unix time (1970). It sounds "right" (to me) but it isn't accurate, at all.
Community
  • 1
  • 1
Christian
  • 27,509
  • 17
  • 111
  • 155
  • Make sure to use four spaces for formatting code so that you get the preformatted text block with syntax highlighting. – Justin Spahr-Summers Dec 24 '10 at 07:50
  • I thought tabs worked as well? – Christian Dec 24 '10 at 07:52
  • I thought it evident from the last paragraph? I'm supposed to get "20", but I get "19.998630136986"; I'm clueless as to where I'm loosing accuracy. – Christian Dec 24 '10 at 08:19
  • **It will NEVER be 20** due to your strange behavior to exclude the leap-year – ajreal Dec 24 '10 at 09:35
  • ajreal - I don't get your point. I'm just removing the excess leap-year seconds, can you explain a bit more than the obvious (we all know it's not 20)? Where's the strange behaviour in removing the leap-seconds? – Christian Dec 24 '10 at 10:10

2 Answers2

1

Could this be related to the inherent inaccuracy experienced when using PHP to manage floating point numbers?

http://php.net/manual/en/language.types.float.php

Luke Stevenson
  • 10,357
  • 2
  • 26
  • 41
1

You should replace 1968 in your calculation (where does it come from ?) by the origine of unix time : 1970 and you will get more accurate results.

Edit

You have to do an intval to count the number of leapyears which must be an integer :

return $time - (intval( (date('Y', $time) - 1969) / 4) * $LEAPDIFF);

This will give you correct results within the range +0 -> +68 , end of unix time on 32bit machine

Toto
  • 89,455
  • 62
  • 89
  • 125
  • There is a leap year every four years, 1972, 1976, 1980... to calculate the amount of leap years since 1970 to Year Y, I use this: `round((Y-1968)/4)` example: `(1976-1968)/4` = `2`. The reason is that 1970 (unix) doesn't coincide with a leap year, thus I decrease it till I get to "Leap Year 0", which would be 1968. – Christian Dec 24 '10 at 10:20
  • Trying your suggestion, I did get accurate results. I'm even more confused :( – Christian Dec 24 '10 at 10:21
  • I've "increased the stakes", form +20 to +60 years, and...I got accurate results. Tried +80, and got a 0 (whereas with mine, it got to a negative number). – Christian Dec 24 '10 at 10:27
  • If the number of the year is specified in a two digit format, the values between 00-69 are mapped to 2000-2069 and 70-99 to 1970-1999. ...possible differences on 32bit systems (possible dates might end on 2038-01-19 03:14:07). – ajreal Dec 24 '10 at 10:42