Get a julian date

From CodeCodex

A Julian date is the number of elapsed days since the beginning of a cycle of 7,980 years invented by Joseph Scaliger in 1583. The purpose of the system is to make it easy to compute an integer (whole number) difference between one calendar date and another calendar date. The starting point for the first Julian cycle began on January 1, 4713 B.C. nd will end on January 22, 3268 (3268-01-22 G). The following day will begin the first day of the second Julian date period (or 7,980 year cycle).

Implementations[edit]

Java[edit]

import java.util.Calendar;
public class JulianDate {
 /**
  * Returns the Julian day number that begins at noon of
  * this day, Positive year signifies A.D., negative year B.C.
  * Remember that the year after 1 B.C. was 1 A.D.
  *
  * ref :
  *  Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
  */
  // Gregorian Calendar adopted Oct. 15, 1582 (2299161)
  public static int JGREG= 15 + 31*(10+12*1582);
  public static double HALFSECOND = 0.5;
  
  public static double toJulian(int[] ymd) {
   int year=ymd[0];
   int month=ymd[1]; // jan=1, feb=2,...
   int day=ymd[2];    
   int julianYear = year;
   if (year < 0) julianYear++;
   int julianMonth = month;
   if (month > 2) {
     julianMonth++;
   }
   else {
     julianYear--;
     julianMonth += 13;
   }
   
   double julian = (java.lang.Math.floor(365.25 * julianYear)
        + java.lang.Math.floor(30.6001*julianMonth) + day + 1720995.0);
   if (day + 31 * (month + 12 * year) >= JGREG) {
     // change over to Gregorian calendar
     int ja = (int)(0.01 * julianYear);
     julian += 2 - ja + (0.25 * ja);
   }
   return java.lang.Math.floor(julian);
 }
 
 /**
 * Converts a Julian day to a calendar date
 * ref :
 * Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
 */
 public static int[] fromJulian(double injulian) {
   int jalpha,ja,jb,jc,jd,je,year,month,day;
   double julian = injulian + HALFSECOND / 86400.0;
   ja = (int) injulian;
   if (ja>= JGREG) {    
     jalpha = (int) (((ja - 1867216) - 0.25) / 36524.25);
     ja = ja + 1 + jalpha - jalpha / 4;
   }
   
   jb = ja + 1524;
   jc = (int) (6680.0 + ((jb - 2439870) - 122.1) / 365.25);
   jd = 365 * jc + jc / 4;
   je = (int) ((jb - jd) / 30.6001);
   day = jb - jd - (int) (30.6001 * je);
   month = je - 1;
   if (month > 12) month = month - 12;
   year = jc - 4715;
   if (month > 2) year--;
   if (year <= 0) year--;
   
   return new int[] {year, month, day};
  }
  
  public static void main(String args[]) {
   // FIRST TEST reference point
   System.out.println("Julian date for May 23, 1968 : "
      + toJulian( new int[] {1968, 5, 23 } ));
   // output : 2440000
   int results[] = fromJulian(toJulian(new int[] {1968, 5, 23 }));
   System.out.println
     ("... back to calendar : " + results[0] + " "
       + results[1] + " " + results[2]);
       
   // SECOND TEST today    
   Calendar today = Calendar.getInstance();
   double todayJulian = toJulian
      (new int[]{today.get(Calendar.YEAR), today.get(Calendar.MONTH)+1, 
       today.get(Calendar.DATE)});
   System.out.println("Julian date for today : " + todayJulian);
   results = fromJulian(todayJulian);
   System.out.println
      ("... back to calendar : " + results[0] + " " + results[1]
       + " " + results[2]);
       
   // THIRD TEST
   double date1 = toJulian(new int[]{2005,1,1});
   double date2 = toJulian(new int[]{2005,1,31});    
   System.out.println("Between 2005-01-01 and 2005-01-31 : "
      + (date2 - date1) + " days");
   
   /*
      expected output :
         Julian date for May 23, 1968 : 2440000.0
         ... back to calendar 1968 5 23
         Julian date for today : 2453487.0
         ... back to calendar 2005 4 26
         Between 2005-01-01 and 2005-01-31 : 30.0 days
   */
   }
 }

Ruby[edit]

require 'date'

# FIRST TEST reference point
str = "May 23, 1968"
date = Date.parse(str)
printf "Julian date for %s : %s\n", str, date.jd
puts date.strftime("... back to calendar %Y %m %d")

# SECOND TEST today
today = Date.today
printf "Julian date for today : %s\n", today.jd
puts today.strftime('... back to calendar %Y %m %d')

# THIRD TEST
date1 = Date.new(2005,1,1)
date2 = Date.parse("2005-01-31")
printf("Between %s and %s : %s days\n", date1, date2, (date2 - date1).to_i)

The execution result

Julian date for May 23, 1968 : 2440000
... back to calendar 1968 05 23
Julian date for today : 2455625
... back to calendar 2011 03 04
Between 2005-01-01 and 2005-01-31 : 30 days

Seed7[edit]

const func integer: julianDayNumber (in time: aTime) is func
  result
    var integer: result is 0;
  local
    var integer: year is 0;
    var integer: month is 0;
  begin
    year := aTime.year;
    month := aTime.month;
    if month <= 2 then
      decr(year);
      month +:= 12;
    end if;
    result := (1461 * (year + 4800)) mdiv 4 +
          (367 * (month - 2)) mdiv 12 -
          (3 * ((year + 4900) mdiv 100)) mdiv 4 +
          aTime.day - 32075;
  end func;

Original source: [1]

const func time: julianDayNumToTime (in integer: julianDayNumber) is func
  result
    var time: result is time.value;
  local
    var integer: l is 0;
    var integer: n is 0;
    var integer: i is 0;
    var integer: j is 0;
  begin
    l := julianDayNumber + 68569;
    n := (4 * l) mdiv 146097;
    l := l - (146097 * n + 3) mdiv 4;
    i := (4000 * (l + 1)) mdiv 1461001;
    l := l - (1461 * i) mdiv 4 + 31;
    j := (80 * l) mdiv 2447;
    result.day := l - (2447 * j) mdiv 80;
    l := j mdiv 11;
    result.month := j + 2 - (12 * l);
    result.year := 100 * (n - 49) + i + l;
  end func;

Original source: [2]

There is a lot of variation around the idea of a "Julian date". You can have the Modified Julian Date (JD) or the Truncated Julian Date (TJD). The main difference is the starting for counting the days.

Before Y2K, many applications (especially mainframe systems) were storing dates in a format called "the Julian format". This format is a 5 digit number, consisting of a 2 digit year and a 3 digit day-of-year number. For example, 17-July-1998 is stored as 98221, since 17-July is the 221th day of the year. This format is not really useful since Y2K! The main reason for using the 5-digits Julian date was to save disk space and still have a format easy to use to handle dates.