date.cpp

#include <iostream>
 
#include "date.h"
 
 
Date::Date()
{
  date = 0;
}
 
long Date::getDate()
{
  return date;
}
 
 
void Date::setDate(long _date)
{
  date = _date;
}
 
 
void Date::setWeekdayOnOrBefore(int _weekday)
{
  date -= (date - _weekday) % 7;
}
 
 
long operator -(const Date& a, const Date& b)
{
  return a.date - b.date;
}
 
 
Date operator +(const Date &a, const long& b)
{
  Date c;
  c.date = a.date + b;
  return c;
}
 
 
/*
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
*/
 
 
DateGregorian::DateGregorian()
{
  year = 0;
  month = 0;
  day = 0;
  date = 0;
}
 
 
DateGregorian::DateGregorian(int _year, int _month, int _day)
{
  setDate(_year, _month, _day);
}
 
 
DateGregorian::DateGregorian(Date _date)
{
//  date = _date.getDate();
  setDate(_date.getDate());
}
 
 
int DateGregorian::getDayOfWeek()
{
  return date % 7;
}
 
 
void DateGregorian::setDate(int _year, int _month, int _day)
{
  year = _year;
  month = _month;
  day = _day;
 
  --_year;
 
  date = 0;
 
  // Now calculate days before this year.
  // Basic years.
  date += _year * 365;
 
  // leap year days.
  date += _year / 4;
 
  // Century non-leap years.
  date -= _year / 100;
 
  // 400 years.
  date += _year / 400;
 
  // Add the days before this month.
  for (int i = 1; i < _month; i++)
    date += daysInMonth(year, i);
 
  date += _day;
}
 
 
void DateGregorian::setDate(long _date)
{
  date = _date;
 
  // Approximate y/m/d from below.
  year = _date / 366;
 
  DateGregorian guess(year, 1, 1);
 
  while (guess.date <= _date)
  {
    guess.setDate(++year, 1, 1);
  }
 
  guess.setDate(--year, 1, 1);
 
  // Now approach the month.
  month = 1;
 
  while (guess.date <= _date)
  {
    guess.setDate(year, ++month, 1);
  }
 
  guess.setDate(year, --month, 1);
 
  // Now get the difference for day of month.
  day = (int)_date - guess.date + 1;
}
 
 
void DateGregorian::print()
{
  std::cout << year << "/" << month << "/" << day;
  std::cout << " (" << date << ")" << std::endl;
}
 
 
void DateGregorian::easter(int _year)
{
  int golden_number = _year % 19 + 1;
  int century = _year / 100 + 1;
  int x = 3 * century / 4 - 12;
  int z = (8 * century + 5) / 25 - 5;
  int d = 5 * _year / 4 - x - 10;  // Sunday.
 
  // epact is a magic number to approximate
  // the full moon by roughly calculating
  // lunar cycles, from the 19 year (rough)
  // golden cycle?
  int epact = (11 * golden_number + 20 + z - x) % 30;
  if (epact == 25 && golden_number > 11)
    epact++;
  if (epact == 24)
    epact++;
 
  // Calculate full moon.
  int n = 44 - epact;
  if (n < 21)
    n += 30;
 
  // Following Sunday.
  n = n + 7 - (d + n) % 7;
 
  // Easter is n - l days after March 1.
  if (n > 31)
    setDate(_year, 4, n - 31);
  else
    setDate(_year, 3, n);
 
}
 
 
 
 
 
/*
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
*/
 
DateJulian::DateJulian()
{
  year = 0;
  month = 0;
  day = 0;
  date = 0;
}
 
 
DateJulian::DateJulian(int _year, int _month, int _day)
{
  setDate(_year, _month, _day);
}
 
 
DateJulian::DateJulian(Date d)
{
  setDate(d.getDate());
}
 
 
 
void DateJulian::setDate(int _year, int _month, int _day)
{
  year = _year;
  month = _month;
  day = _day;
  --_year;
 
  date = 0;
 
  // Now calculate days before this year.
  // Basic years.
  date += _year * 365;
 
  // leap year days.
  date += _year / 4;
 
  // Add the days before this month.
  for (int i = 1; i < _month; i++)
    date += daysInMonth(_year, i);
 
  date += _day;
 
  // Correction for base difference.
  date -= 2;
}
 
 
void DateJulian::setDate(long _date)
{
  date = _date;
 
  // Approximate this.
  year = _date / 366;
 
  DateJulian guess(year, 1, 1);
 
  while (guess.date <= _date)
  {
    guess.setDate(++year, 1, 1);
  }
 
  guess.setDate(--year, 1, 1);
 
  // Now approach the month.
  month = 1;
 
  while (guess.date <= _date)
  {
    guess.setDate(year, ++month, 1);
  }
 
  guess.setDate(year, --month, 1);
 
  // Now get the difference for day of month.
  day = (int)_date - guess.date + 1;
}
 
 
void DateJulian::easter(int _year)
{
  DateJulian paschal_moon(_year, 4, 19); // Presumed.
  int epact = ((11 * _year % 19) + 14) % 30;
 
  // Corrected for calculated moon.
  paschal_moon.setDate(paschal_moon.getDate() - epact);
 
  // Get the following Sunday.
  // This gives the absolute date, but not the Julian Calendar day.
  Date following_sunday;
  following_sunday.setDate(paschal_moon.getDate() + 7);
  following_sunday.setDate(following_sunday.getDate() - (following_sunday.getDate() % 7));
 
  DateJulian easter(following_sunday);
 
  this->date = easter.date;
  this->year = easter.year;
  this->month = easter.month;
  this->day = easter.day;
}