home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / JDN_L.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  6KB  |  177 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /* jdn_l.c -- Julian Day Number computation
  4. **
  5. ** public domain Julian Day Number functions
  6. **
  7. ** Based on formulae originally posted by
  8. **    Tom Van Flandern / Washington, DC / metares@well.sf.ca.us
  9. **       in the UseNet newsgroup sci.astro.
  10. **    Reposted 14 May 1991 in FidoNet C Echo conference by
  11. **       Paul Schlyter (Stockholm)
  12. ** Minor corrections, added JDN to julian, and recast into C by
  13. **    Raymond Gardner  Englewood, Colorado
  14. **
  15. ** Synopsis:
  16. **      long ymd_to_jdnl(int year, int month, int day, int julian_flag)
  17. **      void jdnl_to_ymd(long jdnl, int *year, int *month, int *day,
  18. **                                                      int julian_flag)
  19. **      year is negative if BC
  20. **      if julian_flag is >  0, use Julian calendar
  21. **      if julian_flag is == 0, use Gregorian calendar
  22. **      if julian_flag is <  0, routines decide based on date
  23. **
  24. ** These routines convert Gregorian and Julian calendar dates to and
  25. ** from Julian Day Numbers.  Julian Day Numbers (JDN) are used by
  26. ** astronomers as a date/time measure independent of calendars and
  27. ** convenient for computing the elapsed time between dates.  The JDN
  28. ** for any date/time is the number of days (including fractional
  29. ** days) elapsed since noon, 1 Jan 4713 BC.  Julian Day Numbers were
  30. ** originated by Joseph Scaliger in 1582 and named after his father
  31. ** Julius, not after Julius Caesar.  They are not related to the
  32. ** Julian calendar.
  33. **
  34. ** For dates from 1 Jan 4713 BC thru 12 Dec Feb 32766 AD, ymd_to_jdnl()
  35. ** will give the JDN for noon on that date.  jdnl_to_ymd() will compute
  36. ** the year, month, and day from the JDN.  Years BC are given (and
  37. ** returned) as negative numbers.  Note that there is no year 0 BC;
  38. ** the day before 1 Jan 1 AD is 31 Dec 1 BC.  Note also that 1 BC,
  39. ** 5 BC, etc. are leap years.
  40. **
  41. ** Pope Gregory XIII decreed that the Julian calendar would end on
  42. ** 4 Oct 1582 AD and that the next day would be 15 Oct 1582 in the
  43. ** Gregorian Calendar.  The only other change is that centesimal
  44. ** years (years ending in 00) would no longer be leap years
  45. ** unless divisible by 400.  Britain and its possessions and
  46. ** colonies continued to use the Julian calendar up until 2 Sep
  47. ** 1752, when the next day became 14 Sep 1752 in the Gregorian
  48. ** Calendar.  These routines can be compiled to use either
  49. ** convention.  By default, the British convention will be used.
  50. ** Simply #define PAPAL to use Pope Gregory's convention.
  51. **
  52. ** Each routine takes, as its last argument, a flag to indicate
  53. ** whether to use the Julian or Gregorian calendar convention.  If
  54. ** this flag is negative, the routines decide based on the date
  55. ** itself, using the changeover date described in the preceding
  56. ** paragraph.  If the flag is zero, Gregorian conventions will be used,
  57. ** and if the flag is positive, Julian conventions will be used.
  58. **
  59. ** Proper JDN's are always floating point values so as to include the
  60. ** time as well as the date. These functions avoid the overhead of
  61. ** floating point math by computing only the integral value of the JDN.
  62. */
  63.  
  64. #include "datetime.h"
  65.  
  66. #ifdef PAPAL                    /* Pope Gregory XIII's decree */
  67. #define LASTJULDATE 15821004L   /* last day to use Julian calendar */
  68. #define LASTJULJDN  2299160L    /* jdn of same */
  69. #else                           /* British-American usage */
  70. #define LASTJULDATE 17520902L   /* last day to use Julian calendar */
  71. #define LASTJULJDN  2361221L    /* jdn of same */
  72. #endif
  73.  
  74.  
  75. long ymd_to_jdnl(int y, int m, int d, int julian)
  76. {
  77.         long jdn;
  78.  
  79.         if (julian < 0)         /* set Julian flag if auto set */
  80.                 julian = (((y * 100L) + m) * 100 + d  <=  LASTJULDATE);
  81.  
  82.         if (y < 0)              /* adjust BC year */
  83.                 y++;
  84.  
  85.         if (julian)
  86.                 jdn = 367L * y - 7 * (y + 5001L + (m - 9) / 7) / 4
  87.                 + 275 * m / 9 + d + 1729777L;
  88.         else
  89.                 jdn = (long)(d - 32076)
  90.                 + 1461L * (y + 4800L + (m - 14) / 12) / 4
  91.                 + 367 * (m - 2 - (m - 14) / 12 * 12) / 12
  92.                 - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4
  93.                 + 1;            /* correction by rdg */
  94.  
  95.         return jdn;
  96. }
  97.  
  98.  
  99. void jdnl_to_ymd(long jdn, int *yy, int *mm, int *dd, int julian)
  100. {
  101.         long x, z, m, d, y;
  102.         long daysPer400Years = 146097L;
  103.         long fudgedDaysPer4000Years = 1460970L + 31;
  104.  
  105.         if (julian < 0)                 /* set Julian flag if auto set */
  106.                 julian = (jdn <= LASTJULJDN);
  107.  
  108.         x = jdn + 68569L;
  109.         if ( julian )
  110.         {
  111.                 x += 38;
  112.                 daysPer400Years = 146100L;
  113.                 fudgedDaysPer4000Years = 1461000L + 1;
  114.         }
  115.         z = 4 * x / daysPer400Years;
  116.         x = x - (daysPer400Years * z + 3) / 4;
  117.         y = 4000 * (x + 1) / fudgedDaysPer4000Years;
  118.         x = x - 1461 * y / 4 + 31;
  119.         m = 80 * x / 2447;
  120.         d = x - 2447 * m / 80;
  121.         x = m / 11;
  122.         m = m + 2 - 12 * x;
  123.         y = 100 * (z - 49) + y + x;
  124.  
  125.         *yy = (int)y;
  126.         *mm = (int)m;
  127.         *dd = (int)d;
  128.  
  129.         if (*yy <= 0)                   /* adjust BC years */
  130.                 (*yy)--;
  131. }
  132.  
  133. #ifdef TEST
  134.  
  135. #include <stdio.h>
  136. #include <stdlib.h>
  137.  
  138. int main(int argc, char *argv[])
  139. {
  140.       int day, yr, mo;
  141.       char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  142.                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  143.       long jdn;
  144.  
  145.       if (3 > argc)
  146.       {
  147.             puts("Usage: JDN d m y");
  148.             puts("where: d = day (1 - 31)");
  149.             puts("       m = month (1 - 12)");
  150.             puts("       y = year (1 - 99, 1800 - 3000)");
  151.             return -1;
  152.       }
  153.  
  154.       yr  = atoi(argv[3]);
  155.       mo  = atoi(argv[2]);
  156.       day = atoi(argv[1]);
  157.  
  158.       if (mo < 1 || 12 < mo)
  159.             return -1;
  160.  
  161.       if (day < 1 || 31 < day)
  162.             return -1;
  163.  
  164.       if (100 > yr)
  165.             yr += 1900;
  166.  
  167.       printf("User specified %d-%s-%d...\n\n", day, months[mo - 1], yr);
  168.  
  169.       jdn = ymd_to_jdnl(yr, mo, day, 0);
  170.       jdnl_to_ymd(jdn, &yr, &mo, &day, 0);
  171.  
  172.       printf("jdn_l(%d-%s-%d) = %ld\n", day, months[mo - 1], yr, jdn);
  173.       return 0;
  174. }
  175.  
  176. #endif /* TEST */
  177.