Hebrew date conversion code - ignore if you're not interested



// Luach - a Jewish calendar with halachic times
// Copyright (C) Russell Steinthal, 1999
// See file COPYING for license information

// Implementation of Hebrew date class
// $Header$

// Code in this file is derived from code bearing the following 
license:

/////////// The following C++ code is translated from the Lisp code
/////////// in ``Calendrical Calculations'' by Nachum Dershowitz and
/////////// Edward M. Reingold, Software---Practice & Experience,
/////////// vol. 20, no. 9 (September, 1990), pp. 899--928.

/////////// This code is in the public domain, but any use of it
/////////// should publically acknowledge its source.

#include "Date.h"

static const int HebrewEpoch = -1373429;

HebrewDate::HebrewDate(const SimpleDate& d)
{
  int abs;
  if(d.type == Gregorian)
    abs = (int) GregorianDate(d.d,d.m,d.y);
  else
    abs = (int) HebrewDate(d.d,d.m,d.y);
  FromAbsolute(abs);
}

HebrewDate::HebrewDate(const GregorianDate& d)
{
  FromAbsolute(d);
}

void HebrewDate::FromGregorian(int day, int month, int year)
{
  int abs = (int) GregorianDate(day, month, year);
  FromAbsolute(abs);
}

// Number of days elapsed from the Sunday prior to the start of the
// Hebrew calendar to the mean conjunction of Tishri of Hebrew year.

int HebrewDate::DaysFromCreation(int year) const
{
  int MonthsElapsed =
    (235 * ((year - 1) / 19))           // Months in complete cycles 
so far.
    + (12 * ((year - 1) % 19))          // Regular months in this 
cycle.
    + (7 * ((year - 1) % 19) + 1) / 19; // Leap months this cycle
  int PartsElapsed = 204 + 793 * (MonthsElapsed % 1080);
  int HoursElapsed =
    5 + 12 * MonthsElapsed + 793 * (MonthsElapsed  / 1080)
    + PartsElapsed / 1080;
  int ConjunctionDay = 1 + 29 * MonthsElapsed + HoursElapsed / 24;
  int ConjunctionParts = 1080 * (HoursElapsed % 24) + PartsElapsed % 
1080;
  int AlternativeDay;
  if ((ConjunctionParts >= 19440)        // If new moon is at or 
after midday,
      || (((ConjunctionDay % 7) == 2)    // ...or is on a Tuesday...
          && (ConjunctionParts >= 9924)  // at 9 hours, 204 parts or 
later...
          && !(IsLeapYear(year)))   // ...of a common year,
      || (((ConjunctionDay % 7) == 1)    // ...or is on a Monday at...
          && (ConjunctionParts >= 16789) // 15 hours, 589 parts or 
later...
          && (IsLeapYear(year - 1))))// at the end of a leap year
    // Then postpone Rosh HaShanah one day
    AlternativeDay = ConjunctionDay + 1;
  else
    AlternativeDay = ConjunctionDay;
  if (((AlternativeDay % 7) == 0)// If Rosh HaShanah would occur on 
Sunday,
      || ((AlternativeDay % 7) == 3)     // or Wednesday,
      || ((AlternativeDay % 7) == 5))    // or Friday
    // Then postpone it one (more) day
    return (1+ AlternativeDay);
  else
    return AlternativeDay;
}

inline bool HebrewDate::IsLeapYear(int year) const
{
  return ((((7 * year) + 1) % 19) < 7);
}

inline bool HebrewDate::LongHeshvan(int year) const
{
  return ((DaysInYear(year) % 10) == 5);
}

inline bool HebrewDate::ShortKislev(int year) const
{
  return ((DaysInYear(year) % 10) == 3);
}

inline int HebrewDate::DaysInYear(int year) const
{
  return DaysFromCreation(year+1)-DaysFromCreation(year);
}

inline int HebrewDate::LastDayOfMonth(int month, int year) const
{
  switch(month)
    {
    case 2:
    case 4:
    case 6:
    case 10:
    case 13:
      return 29;
    case 8:
      return LongHeshvan(year) ? 30 : 29;
    case 9:
      return ShortKislev(year) ? 29 : 30;
    case 12:
      return IsLeapYear(year) ? 30 : 29;
    }
  return 30;
}

inline int HebrewDate::LastMonthOfYear(int year) const
{
  return (IsLeapYear(year) ? 13 : 12);
}

void HebrewDate::FromAbsolute(int absDate)
{
  // approximate the year (erring low)
  y = (absDate + HebrewEpoch) / 366;
  // search forward for the correct year from the guess
  while(absDate >= HebrewDate(1,7,y+1))
    y++;
  // search forward for the month from either Tishrei or Nisan
  if(absDate < HebrewDate(1,1,y))
    m = 7;
  else
    m = 1;
  while(absDate > HebrewDate(LastDayOfMonth(m,y), m, y))
    m++;
  // calculate the day by subtraction
  d = absDate - HebrewDate(1,m,y) + 1;
}

// Compute the absolute date from a Hebrew date
HebrewDate::operator int() const
{
  int dayInYear = d; // Days so far this month.
  // Before Tishri, so add days in prior months
  // this year before and after Nisan.
  if(m < 7) 
    { 
      int mon = 7;
      while(mon <= (LastMonthOfYear(y))) 
	{
	  dayInYear = dayInYear + LastDayOfMonth(mon, y);
	  mon++;
	};
      mon = 1;
      while(mon < m) 
	{
	  dayInYear = dayInYear + LastDayOfMonth(mon, y);
	  mon++;
	}
    }
  else 
    { 
      // Add days in prior months this year
      int mon = 7;
      while(mon < m) 
	{
	  dayInYear = dayInYear + LastDayOfMonth(mon, y);
	  mon++;
	}
    }
  return (dayInYear + (DaysFromCreation(y) // Days in prior years.
		       + HebrewEpoch));// Days elapsed before absolute date 1.
}

string HebrewDate::MonthName(int month,int year) const
{
  switch(month)
    {
    case 1: return "Nisan";
    case 2: return "Iyar";
    case 3: return "Sivan";
    case 4: return "Tammuz";
    case 5: return "Av";
    case 6: return "Elul";
    case 7: return "Tishrei";
    case 8: return "Heshvan";
    case 9: return "Kislev";
    case 10: return "Tevet";
    case 11: return "Shvat";
    case 12: return IsLeapYear(year) ? "Adar I" : "Adar";
    case 13: return "Adar II";
     }
  return "Invalid month";
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]