php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49676 date_sunrise() off by several minutes
Submitted: 2009-09-25 21:52 UTC Modified: 2009-09-26 00:53 UTC
From: eclipsechasers2 at yahoo dot com Assigned:
Status: Closed Package: Date/time related
PHP Version: 5.2.11, 5.3.1RC1 , 6 OS: *
Private report: No CVE-ID: None
 [2009-09-25 21:52 UTC] eclipsechasers2 at yahoo dot com
Description:
------------
Although sunset time agrees with many websites, sunrise time is off by several minutes, e.g.:
http://www.timeanddate.com/worldclock/astronomy.html?n=224&month=3&year=2009&obj=sun&afl=-11&day=1
or http://www.sunrisesunset.com/custom_srss_calendar.asp

This is a follow-on problem from bug 49558.
PHP internal code in php_date.c was changed to:
rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, calc_sunset?0:1, &h_rise, &h_set, &rise, &set, &transit)

I believe that calc_sunset?0:1 in that expression should be 1 all the time in order to give correct results for both sunrise and sunset.

Reproduce code:
---------------
<?php
$gregyear = 2009; $gregmonth = 3; $gregday = 1;
$location = "San Francisco"; $latitude = 37.787; $longitude = -122.447;
$timezone = "America/Los_Angeles"; date_default_timezone_set($timezone);
$gregmonthname = JDMonthName(cal_to_jd(CAL_GREGORIAN,$gregmonth,1,2000),1);
$jd = gregoriantojd($gregmonth, $gregday, $gregyear);
  $weekday = jddayofweek($jd,0);
  echo "<b>$gregyear $gregmonthname $dd  - " . jddayofweek($jd,1) . " - ";
  echo "Latitude $latitude Longitude $longitude Time Zone $timezone Location $location</b>\n";
  for ($i = 0; $i <= 30; $i++) {
    list($m11,$d11,$y11) = split('/',jdtogregorian($jd + $i));
    if ($m11 < 10) $m11 = "0" . $m11;
    if ($d11 < 10) $d11 = "0" . $d11;
    $ts = $y11 . "-" . $m11 . "-" . $d11 . " 06:00:00";
    $strts = strtotime($ts);
    $dateobj = new DateTime($ts);
    $gmto = $dateobj->getOffset() / 3600;
    $sunris0 = date_sunrise($strts,SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, 90 + 50/60, $gmto);
    $sunset0 = date_sunset ($strts,SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, 90 + 50/60, $gmto);
    printf("<br>%s %s %s\n",$ts,date("g:i:sa",$sunris0), date("g:i:sa",$sunset0));
    }
?> 

Expected result:
----------------
Last two columns (sunrise and sunset) should generally agree with websites above, e.g.:
Mar 1, 2009	6:41 AM	6:04 PM
Mar 2, 2009	6:39 AM	6:05 PM
Mar 3, 2009	6:38 AM	6:06 PM
Mar 4, 2009	6:37 AM	6:07 PM
Mar 5, 2009	6:35 AM	6:08 PM
Mar 6, 2009	6:34 AM	6:09 PM
Mar 7, 2009	6:32 AM	6:10 PM
Mar 8, 2009	7:31 AM	7:11 PM
Mar 9, 2009	7:29 AM	7:12 PM
Mar 10, 2009	7:28 AM	7:13 PM
Mar 11, 2009	7:26 AM	7:13 PM
Mar 12, 2009	7:25 AM	7:14 PM
Mar 13, 2009	7:23 AM	7:15 PM
Mar 14, 2009	7:22 AM	7:16 PM

Actual result:
--------------
<br>2009-03-01 06:00:00 6:37:59am 6:04:20pm Note excellent agreement
<br>2009-03-02 06:00:00 6:36:35am 6:05:20pm for sunset times,
<br>2009-03-03 06:00:00 6:35:09am 6:06:19pm but relatively large
<br>2009-03-04 06:00:00 6:33:43am 6:07:18pm difference for sunrise.
<br>2009-03-05 06:00:00 6:32:16am 6:08:17pm
<br>2009-03-06 06:00:00 6:30:49am 6:09:16pm
<br>2009-03-07 06:00:00 6:29:21am 6:10:14pm
<br>2009-03-08 06:00:00 7:27:57am 7:11:10pm
<br>2009-03-09 06:00:00 7:26:28am 7:12:08pm
<br>2009-03-10 06:00:00 7:24:59am 7:13:05pm
<br>2009-03-11 06:00:00 7:23:30am 7:14:03pm
<br>2009-03-12 06:00:00 7:22:00am 7:15:00pm
<br>2009-03-13 06:00:00 7:20:30am 7:15:57pm
<br>2009-03-14 06:00:00 7:19:00am 7:16:53pm

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-09-25 23:12 UTC] rasmus@php.net
> I believe that calc_sunset?0:1 in that expression should be 1 all the
> time in order to give correct results for both sunrise and sunset.

That statement doesn't make much sense.  calc_sunset?0:1 means that it is always 0 when calculating the sunset and always 1 when calculating the sunrise, so I don't think that is it.

By the way, your example seems overly complex.  

$db = new DateTime('2009-03-01');
$de = new DateTime('2009-03-14');
$di = DateInterval::createFromDateString('next day');
$dp = new DatePeriod($db, $di, $de);
foreach($dp as $dt) {
   echo $dt->format("M d ").date_sunrise($dt->format("U"),SUNFUNCS_RET_STRING,37.787,-122.447)."\n";
}

 [2009-09-26 00:38 UTC] eclipsechasers2 at yahoo dot com
Thank you for the improved example. I have not done much php coding, and am glad to have the tips.

I do not understand from your comment if it is my suggestion that "doesn't make sense", or the existing code. Assuming that you meant the former, let me explain further. The code for timelib_astro_rise_set_altitude is found in astro.c. For the parameter in question, the comments explain:
 *         upper_limb: non-zero -> upper limb, zero -> center         
 *               Set to non-zero (e.g. 1) when computing rise/set     
 *               times, and to zero when computing start/end of       
 *               twilight.

This suggests, at least to me, that the value should be 1 when computing both sunrise and sunset. However, as coded, it is 1 at sunset (which seems to return the correct time), but 0 for sunrise (which seems not to). I think if the value were always 1, it would always return the correct time (or at least a time consistent with other sites) for both.
 [2009-09-26 00:53 UTC] rasmus@php.net
Ah, I see.  I think I confused twilight with sunset reading those comments before.
 [2009-09-26 00:54 UTC] svn@php.net
Automatic comment from SVN on behalf of rasmus
Revision: http://svn.php.net/viewvc/?view=revision&revision=288834
Log: Refix bug #49558 as per bug #49676
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 19:01:29 2024 UTC