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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: dtorop932 at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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 Dec 03 17:01:29 2024 UTC