php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #30937 date_sunrise() & date_sunset() don't handle endless day/night at high latitudes
Submitted: 2004-11-29 23:21 UTC Modified: 2006-01-04 22:40 UTC
Votes:5
Avg. Score:4.6 ± 0.5
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (33.3%)
From: dtorop932 at gmail dot com Assigned: derick (profile)
Status: Closed Package: Date/time related
PHP Version: 5CVS-2004-11-29 (dev) OS: GNU/Linux
Private report: No CVE-ID: None
 [2004-11-29 23:21 UTC] dtorop932 at gmail dot com
Description:
------------
php_do_date_sunrise_sunset() in ext/standard/sunfuncs.c should know about midnight sun and endless night at high latitudes.  The relevant code to handle this is currently commented out at lines 116-120.

In addition, nonsensical times (such as "-3:-4") can be returned with format SUNFUNCS_RET_STRING due to negative gmt_offset parameters.

It is unclear how this data should be returned, e.g. a descriptive string ("none"?) for SUNFUNCS_RET_STRING.  Also, whether endless day and endless night should somehow be differentiated.

Below is the start of a patch for this.  It is a bit ugly and makes some inelegant decisions of how to represent these cases.  Regardless, the "expected result" below is the output from a patched sunfuncs.c.

--- ext/standard/sunfuncs.c.orig        2004-11-29 15:59:48.000000000 -0500     
+++ ext/standard/sunfuncs.c     2004-11-29 17:09:34.000000000 -0500
@@ -113,11 +113,14 @@
        /* step 7a: calculate the sun's local hour angle */
        cosH = (cos(to_rad(zenith)) - (sinDec * sin(to_rad(latitude)))) / (cosDec * cos(to_rad(latitude)));
 
-       /* XXX: What's the use of this block.. ?
-        * if (!calc_sunset && cosH > 1 || calc_sunset && cosH < -1) {
-        *    throw doesnthappen(); 
-        * }
-        */
+        if (cosH > 1) {
+          /* the sun will not rise */
+          return -1;
+        }
+        if (cosH < -1) {
+          /* the sun will not set */
+          return -2;
+        }
                
        /* step 7b: finish calculating H and convert into hours */
        if (calc_sunset) {
@@ -200,11 +203,37 @@
                        break;
        }
        
-       ret = php_sunrise_sunset(N, latitude, longitude, zenith, calc_sunset) + gmt_offset;
+       ret = php_sunrise_sunset(N, latitude, longitude, zenith, calc_sunset);
+        /* is there no sunrise or sunset? */
+        if (ret < 0) {
+                switch (retformat) {
+                        case SUNFUNCS_RET_TIMESTAMP:
+                                RETURN_LONG((int) ret);
+                                break;
+                        case SUNFUNCS_RET_STRING:
+                                if (ret == -1) {
+                                  RETURN_STRING("none", 1);
+                                } else {
+                                  RETURN_STRING("always up", 1);
+                                }
+                                break;
+                        case SUNFUNCS_RET_DOUBLE:
+                                RETURN_DOUBLE(ret);
+                                break;
+                }
+        }
+
+       ret += gmt_offset;
+       while (ret < 0) {
+               ret += 24;
+       }
+       while (ret > 24) {
+               ret -= 24;
+       }
 
        switch (retformat) {
                case SUNFUNCS_RET_TIMESTAMP:

Reproduce code:
---------------
<?php                   
$longitude = 0;    // arbitrary longitude -- doesn't matter for 

// arbitrarily look at May 15 and November 29, both of which have no sunrise or sunset above 70th latitude
foreach (array("15 May 2004", "20 November 2004") as $date) {
  print "\nDate: $date\n";
  $time = strtotime($date);
  foreach (array("SUNFUNCS_RET_TIMESTAMP", "SUNFUNCS_RET_STRING",
        "SUNFUNCS_RET_DOUBLE") as $format_name) {
    print "  Format: $format_name\n";
    $format = constant($format_name);
    foreach (range(69,72) as $latitude) {
      print "    latitude: $latitude" .
        "  sunrise: " . date_sunrise($time, $format, $latitude, $longitude, 90.83, -5) .
        "  sunset: " . date_sunset($time, $format, $latitude, $longtitude, 90.83, -5) . "\n";
    }
    print "\n";
  }
}
?>

Expected result:
----------------
Date: 15 May 2004
  Format: SUNFUNCS_RET_TIMESTAMP
    latitude: 69  sunrise: 1084580415  sunset: 1084580261
    latitude: 70  sunrise: 1084580364  sunset: 1084580325
    latitude: 71  sunrise: -2  sunset: -2
    latitude: 72  sunrise: -2  sunset: -2

  Format: SUNFUNCS_RET_STRING
    latitude: 69  sunrise: 20:15  sunset: 17:41
    latitude: 70  sunrise: 19:24  sunset: 18:45
    latitude: 71  sunrise: always up  sunset: always up
    latitude: 72  sunrise: always up  sunset: always up

  Format: SUNFUNCS_RET_DOUBLE
    latitude: 69  sunrise: 20.253089585446  sunset: 17.694458258503
    latitude: 70  sunrise: 19.40435878461  sunset: 18.754862725714
    latitude: 71  sunrise: -2  sunset: -2
    latitude: 72  sunrise: -2  sunset: -2


Date: 20 November 2004
  Format: SUNFUNCS_RET_TIMESTAMP
    latitude: 69  sunrise: 1100909101  sunset: 1100909307
    latitude: 70  sunrise: 1100909130  sunset: 1100909276
    latitude: 71  sunrise: -1  sunset: -1
    latitude: 72  sunrise: -1  sunset: -1

  Format: SUNFUNCS_RET_STRING
    latitude: 69  sunrise: 05:01  sunset: 08:27
    latitude: 70  sunrise: 05:30  sunset: 07:56
    latitude: 71  sunrise: none  sunset: none
    latitude: 72  sunrise: none  sunset: none

  Format: SUNFUNCS_RET_DOUBLE
    latitude: 69  sunrise: 5.0176291994972  sunset: 8.4611376500614
    latitude: 70  sunrise: 5.5108334557604  sunset: 7.9447538821896
    latitude: 71  sunrise: -1  sunset: -1
    latitude: 72  sunrise: -1  sunset: -1


Actual result:
--------------
Date: 15 May 2004
  Format: SUNFUNCS_RET_TIMESTAMP
    latitude: 69  sunrise: 1084578976  sunset: 1084580261
    latitude: 70  sunrise: 1084578925  sunset: 1084580325
    latitude: 71  sunrise: -1062904448  sunset: -1062904448
    latitude: 72  sunrise: -1062904448  sunset: -1062904448

  Format: SUNFUNCS_RET_STRING
    latitude: 69  sunrise: -3:-4  sunset: 17:41
    latitude: 70  sunrise: -4:-3  sunset: 18:45
    latitude: 71  sunrise: -2147  sunset: -2147
    latitude: 72  sunrise: -2147  sunset: -2147

  Format: SUNFUNCS_RET_DOUBLE
    latitude: 69  sunrise: -3.746910414554  sunset: 17.694458258503
    latitude: 70  sunrise: -4.5956412153904  sunset: 18.754862725714
    latitude: 71  sunrise: NAN  sunset: NAN
    latitude: 72  sunrise: NAN  sunset: NAN


Date: 20 November 2004
  Format: SUNFUNCS_RET_TIMESTAMP
    latitude: 69  sunrise: 1100909101  sunset: 1100909307
    latitude: 70  sunrise: 1100909130  sunset: 1100909276
    latitude: 71  sunrise: -1046574848  sunset: -1046574848
    latitude: 72  sunrise: -1046574848  sunset: -1046574848

  Format: SUNFUNCS_RET_STRING
    latitude: 69  sunrise: 05:01  sunset: 08:27
    latitude: 70  sunrise: 05:30  sunset: 07:56
    latitude: 71  sunrise: -2147  sunset: -2147
    latitude: 72  sunrise: -2147  sunset: -2147

  Format: SUNFUNCS_RET_DOUBLE
    latitude: 69  sunrise: 5.0176291994972  sunset: 8.4611376500614
    latitude: 70  sunrise: 5.5108334557604  sunset: 7.9447538821896
    latitude: 71  sunrise: NAN  sunset: NAN
    latitude: 72  sunrise: NAN  sunset: NAN



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-01-04 22:40 UTC] derick@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 10:01:30 2024 UTC