PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/calendar - gregor.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 39 44 88.6 %
Date: 2014-09-13 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $selId: gregor.c,v 2.0 1995/10/24 01:13:06 lees Exp $
       2             :  * Copyright 1993-1995, Scott E. Lee, all rights reserved.
       3             :  * Permission granted to use, copy, modify, distribute and sell so long as
       4             :  * the above copyright and this permission statement are retained in all
       5             :  * copies.  THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
       6             :  */
       7             : 
       8             : /**************************************************************************
       9             :  *
      10             :  * These are the externally visible components of this file:
      11             :  *
      12             :  *     void
      13             :  *     SdnToGregorian(
      14             :  *         long int  sdn,
      15             :  *         int      *pYear,
      16             :  *         int      *pMonth,
      17             :  *         int      *pDay);
      18             :  *
      19             :  * Convert a SDN to a Gregorian calendar date.  If the input SDN is less
      20             :  * than 1, the three output values will all be set to zero, otherwise
      21             :  * *pYear will be >= -4714 and != 0; *pMonth will be in the range 1 to 12
      22             :  * inclusive; *pDay will be in the range 1 to 31 inclusive.
      23             :  *
      24             :  *     long int
      25             :  *     GregorianToSdn(
      26             :  *         int inputYear,
      27             :  *         int inputMonth,
      28             :  *         int inputDay);
      29             :  *
      30             :  * Convert a Gregorian calendar date to a SDN.  Zero is returned when the
      31             :  * input date is detected as invalid or out of the supported range.  The
      32             :  * return value will be > 0 for all valid, supported dates, but there are
      33             :  * some invalid dates that will return a positive value.  To verify that a
      34             :  * date is valid, convert it to SDN and then back and compare with the
      35             :  * original.
      36             :  *
      37             :  *     char *MonthNameShort[13];
      38             :  *
      39             :  * Convert a Gregorian month number (1 to 12) to the abbreviated (three
      40             :  * character) name of the Gregorian month (null terminated).  An index of
      41             :  * zero will return a zero length string.
      42             :  *
      43             :  *     char *MonthNameLong[13];
      44             :  *
      45             :  * Convert a Gregorian month number (1 to 12) to the name of the Gregorian
      46             :  * month (null terminated).  An index of zero will return a zero length
      47             :  * string.
      48             :  *
      49             :  * VALID RANGE
      50             :  *
      51             :  *     4714 B.C. to at least 10000 A.D.
      52             :  *
      53             :  *     Although this software can handle dates all the way back to 4714
      54             :  *     B.C., such use may not be meaningful.  The Gregorian calendar was
      55             :  *     not instituted until October 15, 1582 (or October 5, 1582 in the
      56             :  *     Julian calendar).  Some countries did not accept it until much
      57             :  *     later.  For example, Britain converted in 1752, The USSR in 1918 and
      58             :  *     Greece in 1923.  Most European countries used the Julian calendar
      59             :  *     prior to the Gregorian.
      60             :  *
      61             :  * CALENDAR OVERVIEW
      62             :  *
      63             :  *     The Gregorian calendar is a modified version of the Julian calendar.
      64             :  *     The only difference being the specification of leap years.  The
      65             :  *     Julian calendar specifies that every year that is a multiple of 4
      66             :  *     will be a leap year.  This leads to a year that is 365.25 days long,
      67             :  *     but the current accepted value for the tropical year is 365.242199
      68             :  *     days.
      69             :  *
      70             :  *     To correct this error in the length of the year and to bring the
      71             :  *     vernal equinox back to March 21, Pope Gregory XIII issued a papal
      72             :  *     bull declaring that Thursday October 4, 1582 would be followed by
      73             :  *     Friday October 15, 1582 and that centennial years would only be a
      74             :  *     leap year if they were a multiple of 400.  This shortened the year
      75             :  *     by 3 days per 400 years, giving a year of 365.2425 days.
      76             :  *
      77             :  *     Another recently proposed change in the leap year rule is to make
      78             :  *     years that are multiples of 4000 not a leap year, but this has never
      79             :  *     been officially accepted and this rule is not implemented in these
      80             :  *     algorithms.
      81             :  *
      82             :  * ALGORITHMS
      83             :  *
      84             :  *     The calculations are based on three different cycles: a 400 year
      85             :  *     cycle of leap years, a 4 year cycle of leap years and a 5 month
      86             :  *     cycle of month lengths.
      87             :  *
      88             :  *     The 5 month cycle is used to account for the varying lengths of
      89             :  *     months.  You will notice that the lengths alternate between 30
      90             :  *     and 31 days, except for three anomalies: both July and August
      91             :  *     have 31 days, both December and January have 31, and February
      92             :  *     is less than 30.  Starting with March, the lengths are in a
      93             :  *     cycle of 5 months (31, 30, 31, 30, 31):
      94             :  *
      95             :  *         Mar   31 days  \
      96             :  *         Apr   30 days   |
      97             :  *         May   31 days    > First cycle
      98             :  *         Jun   30 days   |
      99             :  *         Jul   31 days  /
     100             :  *
     101             :  *         Aug   31 days  \
     102             :  *         Sep   30 days   |
     103             :  *         Oct   31 days    > Second cycle
     104             :  *         Nov   30 days   |
     105             :  *         Dec   31 days  /
     106             :  *
     107             :  *         Jan   31 days  \
     108             :  *         Feb 28/9 days   |
     109             :  *                          > Third cycle (incomplete)
     110             :  *
     111             :  *     For this reason the calculations (internally) assume that the
     112             :  *     year starts with March 1.
     113             :  *
     114             :  * TESTING
     115             :  *
     116             :  *     This algorithm has been tested from the year 4714 B.C. to 10000
     117             :  *     A.D.  The source code of the verification program is included in
     118             :  *     this package.
     119             :  *
     120             :  * REFERENCES
     121             :  *
     122             :  *     Conversions Between Calendar Date and Julian Day Number by Robert J.
     123             :  *     Tantzen, Communications of the Association for Computing Machinery
     124             :  *     August 1963.  (Also published in Collected Algorithms from CACM,
     125             :  *     algorithm number 199).
     126             :  *
     127             :  **************************************************************************/
     128             : 
     129             : #include "sdncal.h"
     130             : #include <limits.h>
     131             : 
     132             : #define GREGOR_SDN_OFFSET         32045
     133             : #define DAYS_PER_5_MONTHS  153
     134             : #define DAYS_PER_4_YEARS   1461
     135             : #define DAYS_PER_400_YEARS 146097
     136             : 
     137         132 : void SdnToGregorian(
     138             :                                            long int sdn,
     139             :                                            int *pYear,
     140             :                                            int *pMonth,
     141             :                                            int *pDay)
     142             : {
     143             :         int century;
     144             :         int year;
     145             :         int month;
     146             :         int day;
     147             :         long int temp;
     148             :         int dayOfYear;
     149             : 
     150         132 :         if (sdn <= 0 ||
     151             :                         sdn > (LONG_MAX - 4 * GREGOR_SDN_OFFSET) / 4) {
     152             :                 goto fail;
     153             :         }
     154         128 :         temp = (sdn + GREGOR_SDN_OFFSET) * 4 - 1;
     155             : 
     156             :         /* Calculate the century (year/100). */
     157         128 :         century = temp / DAYS_PER_400_YEARS;
     158             : 
     159             :         /* Calculate the year and day of year (1 <= dayOfYear <= 366). */
     160         128 :         temp = ((temp % DAYS_PER_400_YEARS) / 4) * 4 + 3;
     161         128 :         year = (century * 100) + (temp / DAYS_PER_4_YEARS);
     162         128 :         dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1;
     163             : 
     164             :         /* Calculate the month and day of month. */
     165         128 :         temp = dayOfYear * 5 - 3;
     166         128 :         month = temp / DAYS_PER_5_MONTHS;
     167         128 :         day = (temp % DAYS_PER_5_MONTHS) / 5 + 1;
     168             : 
     169             :         /* Convert to the normal beginning of the year. */
     170         128 :         if (month < 10) {
     171         103 :                 month += 3;
     172             :         } else {
     173          25 :                 year += 1;
     174          25 :                 month -= 9;
     175             :         }
     176             : 
     177             :         /* Adjust to the B.C./A.D. type numbering. */
     178         128 :         year -= 4800;
     179         128 :         if (year <= 0)
     180           0 :                 year--;
     181             : 
     182         128 :         *pYear = year;
     183         128 :         *pMonth = month;
     184         128 :         *pDay = day;
     185         128 :         return;
     186             : 
     187             : fail:
     188           4 :         *pYear = 0;
     189           4 :         *pMonth = 0;
     190           4 :         *pDay = 0;
     191             : }
     192             : 
     193          32 : long int GregorianToSdn(
     194             :                                                    int inputYear,
     195             :                                                    int inputMonth,
     196             :                                                    int inputDay)
     197             : {
     198             :         int year;
     199             :         int month;
     200             : 
     201             :         /* check for invalid dates */
     202          32 :         if (inputYear == 0 || inputYear < -4714 ||
     203             :                 inputMonth <= 0 || inputMonth > 12 ||
     204             :                 inputDay <= 0 || inputDay > 31) {
     205           4 :                 return (0);
     206             :         }
     207             :         /* check for dates before SDN 1 (Nov 25, 4714 B.C.) */
     208          28 :         if (inputYear == -4714) {
     209           0 :                 if (inputMonth < 11) {
     210           0 :                         return (0);
     211             :                 }
     212           0 :                 if (inputMonth == 11 && inputDay < 25) {
     213           0 :                         return (0);
     214             :                 }
     215             :         }
     216             :         /* Make year always a positive number. */
     217          28 :         if (inputYear < 0) {
     218           1 :                 year = inputYear + 4801;
     219             :         } else {
     220          27 :                 year = inputYear + 4800;
     221             :         }
     222             : 
     223             :         /* Adjust the start of the year. */
     224          28 :         if (inputMonth > 2) {
     225          20 :                 month = inputMonth - 3;
     226             :         } else {
     227           8 :                 month = inputMonth + 9;
     228           8 :                 year--;
     229             :         }
     230             : 
     231          56 :         return (((year / 100) * DAYS_PER_400_YEARS) / 4
     232          28 :                         + ((year % 100) * DAYS_PER_4_YEARS) / 4
     233          28 :                         + (month * DAYS_PER_5_MONTHS + 2) / 5
     234          28 :                         + inputDay
     235          28 :                         - GREGOR_SDN_OFFSET);
     236             : }
     237             : 
     238             : char *MonthNameShort[13] =
     239             : {
     240             :         "",
     241             :         "Jan",
     242             :         "Feb",
     243             :         "Mar",
     244             :         "Apr",
     245             :         "May",
     246             :         "Jun",
     247             :         "Jul",
     248             :         "Aug",
     249             :         "Sep",
     250             :         "Oct",
     251             :         "Nov",
     252             :         "Dec"
     253             : };
     254             : 
     255             : char *MonthNameLong[13] =
     256             : {
     257             :         "",
     258             :         "January",
     259             :         "February",
     260             :         "March",
     261             :         "April",
     262             :         "May",
     263             :         "June",
     264             :         "July",
     265             :         "August",
     266             :         "September",
     267             :         "October",
     268             :         "November",
     269             :         "December"
     270             : };

Generated by: LCOV version 1.10

Generated at Sat, 13 Sep 2014 16:24:23 +0000 (2 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.