summaryrefslogtreecommitdiffstats
path: root/korganizer/plugins/hebrew/converter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'korganizer/plugins/hebrew/converter.cpp')
-rw-r--r--korganizer/plugins/hebrew/converter.cpp345
1 files changed, 345 insertions, 0 deletions
diff --git a/korganizer/plugins/hebrew/converter.cpp b/korganizer/plugins/hebrew/converter.cpp
new file mode 100644
index 000000000..1381292e6
--- /dev/null
+++ b/korganizer/plugins/hebrew/converter.cpp
@@ -0,0 +1,345 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Jonathan Singer *
+ * Calendar routines from Hebrew Calendar by Frank Yellin *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "converter.h"
+#include <klocale.h>
+
+Converter::Converter()
+{
+
+}
+
+Converter::~Converter()
+{
+}
+
+long Converter::absolute_from_gregorian(int year, int month, int day)
+{
+ int xyear, day_number;
+
+ xyear = year - 1;
+ day_number = day + 31 * (month - 1);
+ if (month > 2)
+ {
+ day_number -= (23 + (4 * month)) / 10;
+ if (gregorian_leap_year_p(year))
+ day_number++;
+ }
+ return day_number + /* the day number within the current year */
+ 365L * xyear + /* days in prior years */
+ (xyear / 4) + /* Julian leap years */
+ (-(xyear / 100)) + /* deduct century years */
+ (xyear / 400); /* add Gregorian leap years */
+}
+
+/* Given a Hebrew date, calculate the number of days since
+ * January 0, 0001, Gregorian
+ */
+long Converter::absolute_from_hebrew(int year, int month, int day)
+{
+ long sum = day + hebrew_elapsed_days(year) - 1373429L;
+ int i;
+
+ if (month < 7)
+ {
+ int months = hebrew_months_in_year(year);
+
+ for (i = 7; i <= months; ++i)
+ sum += hebrew_month_length(year, i);
+ for (i = 1; i < month; ++i)
+ sum += hebrew_month_length(year, i);
+ }
+ else
+ {
+ for (i = 7; i < month; ++i)
+ sum += hebrew_month_length(year, i);
+ }
+ return sum;
+}
+
+/* Given an absolute date, calculate the gregorian date */
+void
+ Converter::gregorian_from_absolute(long date, int *yearp,
+ int *monthp, int *dayp)
+{
+ int year, month, day;
+
+ for (year = date / 366;
+ date >= absolute_from_gregorian(year + 1, 1, 1); ++year) ;
+ for (month = 1;
+ (month <= 11)
+ && (date >= absolute_from_gregorian(year, 1 + month, 1));
+ ++month ) ;
+ day = 1 + date - absolute_from_gregorian(year, month, 1);
+ *yearp = year;
+ *monthp = month;
+ *dayp = day;
+}
+
+/* Given an absolute date, calculate the Hebrew date */
+void
+ Converter::hebrew_from_absolute(long date, int *yearp, int *monthp,
+ int *dayp)
+{
+ int year, month, day, gyear, gmonth, gday, months;
+
+ gregorian_from_absolute(date, &gyear, &gmonth, &gday);
+ year = gyear + 3760;
+ while (date >= absolute_from_hebrew(1 + year, 7, 1))
+ year++;
+ months = hebrew_months_in_year(year);
+ for (month = 7;
+ date > absolute_from_hebrew(year, month,
+ hebrew_month_length(year, month));
+ month = 1 + (month % months)) ;
+ day = 1 + date - absolute_from_hebrew(year, month, 1);
+ *yearp = year;
+ *monthp = month;
+ *dayp = day;
+}
+
+/* Number of months in a Hebrew year */
+int Converter::hebrew_months_in_year(int year)
+{
+ if (hebrew_leap_year_p(year))
+ return 13;
+ else
+ return 12;
+}
+
+enum
+{ Nissan =
+ 1, Iyar, Sivan, Tamuz, Ab, Elul, Tishrei, Cheshvan, Kislev, Tevet,
+ Shvat, Adar, AdarII, AdarI = 12
+};
+
+enum
+{ January =
+ 1, February, March, April, May, June, July, August, September,
+ October, November, December
+};
+
+/* Number of days in a Hebrew month */
+int Converter::hebrew_month_length(int year, int month)
+{
+ switch (month)
+ {
+ case Tishrei:
+ case Shvat:
+ case Nissan:
+ case Sivan:
+ case Ab:
+ return 30;
+
+ case Tevet:
+ case Iyar:
+ case Tamuz:
+ case Elul:
+ case AdarII:
+ return 29;
+
+ case Cheshvan:
+ // 29 days, unless it's a long year.
+ if ((hebrew_year_length(year) % 10) == 5)
+ return 30;
+ else
+ return 29;
+
+ case Kislev:
+ // 30 days, unless it's a short year.
+ if ((hebrew_year_length(year) % 10) == 3)
+ return 29;
+ else
+ return 30;
+
+ case Adar:
+ // Adar (non-leap year) has 29 days. Adar I has 30 days.
+ if (hebrew_leap_year_p(year))
+ return 30;
+ else
+ return 29;
+
+ default:
+ return 0;
+ }
+}
+
+/* Number of days in a Julian or gregorian month */
+int
+ Converter::secular_month_length(int year,
+ int month /*, bool julianp */ )
+{
+ switch (month)
+ {
+ case January:
+ case March:
+ case May:
+ case July:
+ case August:
+ case October:
+ case December:
+ return 31;
+ case April:
+ case June:
+ case September:
+ case November:
+ return 30;
+ case February:
+ if (gregorian_leap_year_p(year))
+ return 29;
+ else
+ return 28;
+ default:
+ return 0;
+ }
+}
+
+/* Is it a Leap year in the gregorian calendar */
+bool Converter::gregorian_leap_year_p(int year)
+{
+ if ((year % 4) != 0)
+ return 0;
+ if ((year % 400) == 0)
+ return 1;
+ if ((year % 100) == 0)
+ return 0;
+ return 1;
+}
+
+/* Is it a leap year in the Jewish Calendar */
+bool Converter::hebrew_leap_year_p(int year)
+{
+ switch (year % 19)
+ {
+ case 0:
+ case 3:
+ case 6:
+ case 8:
+ case 11:
+ case 14:
+ case 17:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Return the number of days from 1 Tishrei 0001 to the beginning of the given year.
+ * Since this routine gets called frequently with the same year arguments, we cache
+ * the most recent values.
+ */
+#define MEMORY 5
+long Converter::hebrew_elapsed_days(int year)
+{
+ static int saved_year[MEMORY] = { -1, -1, -1, -1, -1 };
+ static long saved_value[MEMORY];
+ int i;
+
+ for (i = 0; i < MEMORY; ++i)
+ if (year == saved_year[i])
+ return saved_value[i];
+ for (i = 0; i < MEMORY-1; ++i) {
+ saved_year[i] = saved_year[1 + i];
+ saved_value[i] = saved_value[1 + i];
+ }
+ saved_year[MEMORY - 1] = year;
+ saved_value[MEMORY - 1] = hebrew_elapsed_days2(year);
+ return saved_value[MEMORY - 1];
+}
+
+long Converter::hebrew_elapsed_days2(int year)
+{
+ long prev_year = year - 1;
+ long months_elapsed = 235L * (prev_year / 19) /* months in complete cycles so far */
+ + 12L * (prev_year % 19) /* regular months in this cycle */
+ + (((prev_year % 19) * 7 + 1) / 19); /* leap months this cycle */
+ long parts_elapsed = 5604 + 13753 * months_elapsed;
+ long day = 1 + 29 * months_elapsed + parts_elapsed / 25920;
+ long parts = parts_elapsed % 25920;
+ int weekday = (day % 7);
+ long alt_day = ((parts >= 19440)
+ || (weekday == 2 && (parts >= 9924)
+ && !hebrew_leap_year_p(year)) || (weekday == 1
+ && (parts >=
+ 16789)
+ &&
+ hebrew_leap_year_p
+ (prev_year)))
+ ? day + 1 : day;
+ switch (alt_day % 7)
+ {
+ case 0:
+ case 3:
+ case 5:
+ return 1 + alt_day;
+ default:
+ return alt_day;
+ }
+}
+
+/* Number of days in the given Hebrew year */
+int Converter::hebrew_year_length(int year)
+{
+ return hebrew_elapsed_days(1 + year) - hebrew_elapsed_days(year);
+}
+
+/* Fill in the DateResult structure based on the given secular date */
+void
+ Converter::SecularToHebrewConversion(int syear, int smonth,
+ int sday,
+ struct DateResult *result)
+{
+ int hyear, hmonth, hday;
+ long absolute;
+
+ absolute = absolute_from_gregorian(syear, smonth, sday);
+
+ hebrew_from_absolute(absolute, &hyear, &hmonth, &hday);
+
+ result->year = hyear;
+ result->month = hmonth;
+ result->day = hday;
+ finish_up(absolute, hyear, hmonth, syear, smonth, result);
+}
+
+/* Fill in the DateResult structure based on the given Hebrew date */
+void
+ Converter::HebrewToSecularConversion(int hyear, int hmonth,
+ int hday,
+ struct DateResult *result)
+{
+ int syear, smonth, sday;
+ long absolute;
+
+ absolute = absolute_from_hebrew(hyear, hmonth, hday);
+ gregorian_from_absolute(absolute, &syear, &smonth, &sday);
+ result->year = hyear;
+ result->month = hmonth;
+ result->day = hday;
+ finish_up(absolute, hyear, hmonth, syear, smonth, result);
+}
+
+/* This is common code for filling up the DateResult structure */
+void
+ Converter::finish_up(long absolute, int hyear, int hmonth,
+ int syear, int smonth,
+ struct DateResult *result)
+{
+ result->hebrew_month_length = hebrew_month_length(hyear, hmonth);
+ result->secular_month_length = secular_month_length(syear, smonth);
+ result->hebrew_leap_year_p = hebrew_leap_year_p(hyear);
+ result->secular_leap_year_p = gregorian_leap_year_p(syear);
+ result->kvia = (hebrew_year_length(hyear) % 10) - 3;
+ // absolute is -1 on 1/1/0001 Julian
+ result->day_of_week = (7 + absolute) % 7;
+ result->hebrew_day_number =
+ absolute - absolute_from_hebrew(hyear, 7, 1) + 1;
+
+}