summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/jdn.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/jdn.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/jdn.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/jdn.c b/reference/C/CONTRIB/SNIP/jdn.c
new file mode 100755
index 0000000..5f69923
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/jdn.c
@@ -0,0 +1,124 @@
+/* jdn.c -- Julian Day Number computation
+**
+** public domain Julian Day Number functions
+**
+** Based on formulae originally posted by
+** Tom Van Flandern / Washington, DC / metares@well.sf.ca.us
+** in the UseNet newsgroup sci.astro.
+** Reposted 14 May 1991 in FidoNet C Echo conference by
+** Paul Schlyter (Stockholm)
+** Minor corrections, added JDN to julian, and recast into C by
+** Raymond Gardner Englewood, Colorado
+**
+** Synopsis:
+** long ymd_to_jdn(int year, int month, int day, int julian_flag)
+** void jdn_to_ymd(long jdn, int *year, int *month, int *day,
+** int julian_flag)
+** year is negative if BC
+** if julian_flag is > 0, use Julian calendar
+** if julian_flag is == 0, use Gregorian calendar
+** if julian_flag is < 0, routines decide based on date
+**
+** These routines convert Gregorian and Julian calendar dates to and
+** from Julian Day Numbers. Julian Day Numbers (JDN) are used by
+** astronomers as a date/time measure independent of calendars and
+** convenient for computing the elapsed time between dates. The JDN
+** for any date/time is the number of days (including fractional
+** days) elapsed since noon, 1 Jan 4713 BC. Julian Day Numbers were
+** originated by Joseph Scaliger in 1582 and named after his father
+** Julius, not after Julius Caesar. They are not related to the
+** Julian calendar.
+**
+** For dates from 1 Jan 4713 BC thru 12 Dec Feb 32766 AD, ymd_to_jdn()
+** will give the JDN for noon on that date. jdn_to_ymd() will compute
+** the year, month, and day from the JDN. Years BC are given (and
+** returned) as negative numbers. Note that there is no year 0 BC;
+** the day before 1 Jan 1 AD is 31 Dec 1 BC. Note also that 1 BC,
+** 5 BC, etc. are leap years.
+**
+** Pope Gregory XIII decreed that the Julian calendar would end on
+** 4 Oct 1582 AD and that the next day would be 15 Oct 1582 in the
+** Gregorian Calendar. The only other change is that centesimal
+** years (years ending in 00) would no longer be leap years
+** unless divisible by 400. Britain and its possessions and
+** colonies continued to use the Julian calendar up until 2 Sep
+** 1752, when the next day became 14 Sep 1752 in the Gregorian
+** Calendar. These routines can be compiled to use either
+** convention. By default, the British convention will be used.
+** Simply #define PAPAL to use Pope Gregory's convention.
+**
+** Each routine takes, as its last argument, a flag to indicate
+** whether to use the Julian or Gregorian calendar convention. If
+** this flag is negative, the routines decide based on the date
+** itself, using the changeover date described in the preceding
+** paragraph. If the flag is zero, Gregorian conventions will be used,
+** and if the flag is positive, Julian conventions will be used.
+*/
+
+
+#ifdef PAPAL /* Pope Gregory XIII's decree */
+#define LASTJULDATE 15821004L /* last day to use Julian calendar */
+#define LASTJULJDN 2299160L /* jdn of same */
+#else /* British-American usage */
+#define LASTJULDATE 17520902L /* last day to use Julian calendar */
+#define LASTJULJDN 2361221L /* jdn of same */
+#endif
+
+
+long ymd_to_jdn(int y, int m, int d, int julian)
+{
+ long jdn;
+
+ if (julian < 0) /* set Julian flag if auto set */
+ julian = (((y * 100L) + m) * 100 + d <= LASTJULDATE);
+
+ if (y < 0) /* adjust BC year */
+ y++;
+
+ if (julian)
+ jdn = 367L * y - 7 * (y + 5001L + (m - 9) / 7) / 4
+ + 275 * m / 9 + d + 1729777L;
+ else
+ jdn = (long)(d - 32076)
+ + 1461L * (y + 4800L + (m - 14) / 12) / 4
+ + 367 * (m - 2 - (m - 14) / 12 * 12) / 12
+ - 3 * ((y + 4900L + (m - 14) / 12) / 100) / 4
+ + 1; /* correction by rdg */
+
+ return jdn;
+}
+
+
+void jdn_to_ymd(long jdn, int *yy, int *mm, int *dd, int julian)
+{
+ long x, z, m, d, y;
+ long daysPer400Years = 146097L;
+ long fudgedDaysPer4000Years = 1460970L + 31;
+
+ if (julian < 0) /* set Julian flag if auto set */
+ julian = (jdn <= LASTJULJDN);
+
+ x = jdn + 68569L;
+ if ( julian )
+ {
+ x += 38;
+ daysPer400Years = 146100L;
+ fudgedDaysPer4000Years = 1461000L + 1;
+ }
+ z = 4 * x / daysPer400Years;
+ x = x - (daysPer400Years * z + 3) / 4;
+ y = 4000 * (x + 1) / fudgedDaysPer4000Years;
+ x = x - 1461 * y / 4 + 31;
+ m = 80 * x / 2447;
+ d = x - 2447 * m / 80;
+ x = m / 11;
+ m = m + 2 - 12 * x;
+ y = 100 * (z - 49) + y + x;
+
+ *yy = (int)y;
+ *mm = (int)m;
+ *dd = (int)d;
+
+ if (*yy <= 0) /* adjust BC years */
+ (*yy)--;
+}