GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-jalali.c
1 /* This file is part of:
2  * Jalali, a Gregorian to Jalali and inverse date convertor
3  * Copyright (C) 2001 Roozbeh Pournader <[email protected]>
4  * Copyright (C) 2001 Mohammad Toossi <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You can receive a copy of GNU Lesser General Public License at the
17  * World Wide Web address <http://www.gnu.org/licenses/lgpl.html>.
18  *
19  * For licensing issues, contact The FarsiWeb Project Group,
20  * Computing Center, Sharif University of Technology,
21  * PO Box 11365-8515, Tehran, Iran, or contact us the
22  * email address <[email protected]>.
23  */
24 
25 /* Changes:
26  *
27  * 2005-Sep-06:
28  * General cleanup --Behdad Esfahbod
29  *
30  * 2001-Sep-21:
31  * Fixed a bug with "30 Esfand" dates, reported by Mahmoud Ghandi
32  *
33  * 2001-Sep-20:
34  * First LGPL release, with both sides of conversions
35  */
36 
37 
38 #include "gnc-jalali.h"
39 
40 
41 /* implementation */
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <glib.h>
46 
47 int g_days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
48 int j_days_in_month[12] = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
49 const char *j_month_name[12] =
50 {
51  "Farvardin", "Ordibehesht", "Khordad",
52  "Tir", "Mordad", "Shahrivar",
53  "Mehr", "Aban", "Azar",
54  "Dey", "Bahman", "Esfand"
55 };
56 
57 int gnc_jalali_days_in_month(int month_index)
58 {
59  g_assert(month_index < 12);
60  return j_days_in_month[month_index];
61 }
62 
63 const char* gnc_jalali_month_name(int month_index)
64 {
65  g_assert(month_index < 12);
66  return j_month_name[month_index];
67 }
68 
69 void gnc_gregorian_to_jalali(int *j_y, int *j_m, int *j_d,
70  int g_y, int g_m, int g_d)
71 {
72  int gy, gm, gd;
73  int jy, jm, jd;
74  long g_day_no, j_day_no;
75  int j_np;
76 
77  int i;
78 
79  gy = g_y - 1600;
80  gm = g_m - 1;
81  gd = g_d - 1;
82 
83  g_day_no = 365 * gy + (gy + 3) / 4 - (gy + 99) / 100 + (gy + 399) / 400;
84  for (i = 0; i < gm; ++i)
85  g_day_no += g_days_in_month[i];
86  if (gm > 1 && ((gy % 4 == 0 && gy % 100 != 0) || (gy % 400 == 0)))
87  /* leap and after Feb */
88  ++g_day_no;
89  g_day_no += gd;
90 
91  j_day_no = g_day_no - 79;
92 
93  j_np = j_day_no / 12053;
94  j_day_no %= 12053;
95 
96  jy = 979 + 33 * j_np + 4 * (j_day_no / 1461);
97  j_day_no %= 1461;
98 
99  if (j_day_no >= 366)
100  {
101  jy += (j_day_no - 1) / 365;
102  j_day_no = (j_day_no - 1) % 365;
103  }
104 
105  for (i = 0; i < 11 && j_day_no >= j_days_in_month[i]; ++i)
106  {
107  j_day_no -= j_days_in_month[i];
108  }
109  jm = i + 1;
110  jd = j_day_no + 1;
111  *j_y = jy;
112  *j_m = jm;
113  *j_d = jd;
114 }
115 
116 void gnc_jalali_to_gregorian(int *g_y, int *g_m, int *g_d,
117  int j_y, int j_m, int j_d)
118 {
119  int gy, gm, gd;
120  int jy, jm, jd;
121  long g_day_no, j_day_no;
122  int leap;
123 
124  int i;
125 
126  jy = j_y - 979;
127  jm = j_m - 1;
128  jd = j_d - 1;
129 
130  j_day_no = 365 * jy + (jy / 33) * 8 + (jy % 33 + 3) / 4;
131  for (i = 0; i < jm; ++i)
132  j_day_no += j_days_in_month[i];
133 
134  j_day_no += jd;
135 
136  g_day_no = j_day_no + 79;
137 
138  gy = 1600 + 400 * (g_day_no / 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
139  g_day_no = g_day_no % 146097;
140 
141  leap = 1;
142  if (g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
143  {
144  g_day_no--;
145  gy += 100 * (g_day_no / 36524); /* 36524 = 365*100 + 100/4 - 100/100 */
146  g_day_no = g_day_no % 36524;
147 
148  if (g_day_no >= 365)
149  g_day_no++;
150  else
151  leap = 0;
152  }
153 
154  gy += 4 * (g_day_no / 1461); /* 1461 = 365*4 + 4/4 */
155  g_day_no %= 1461;
156 
157  if (g_day_no >= 366)
158  {
159  leap = 0;
160 
161  g_day_no--;
162  gy += g_day_no / 365;
163  g_day_no = g_day_no % 365;
164  }
165 
166  for (i = 0; g_day_no >= g_days_in_month[i] + (i == 1 && leap); i++)
167  g_day_no -= g_days_in_month[i] + (i == 1 && leap);
168  gm = i + 1;
169  gd = g_day_no + 1;
170 
171  *g_y = gy;
172  *g_m = gm;
173  *g_d = gd;
174 }
175 
176 #if 0
177 int
178 main(void)
179 {
180  int y, m, d;
181  time64 bin_time;
182  struct tm br_time;
183 
184  gnc_time (&bin_time);
185  gnc_localtime_r (&bin_time, &br_time);
186 
187  gregorian_to_jalali(&y, &m, &d,
188  1900 + br_time.tm_year,
189  1 + br_time.tm_mon,
190  br_time.tm_mday);
191 
192  printf("Current Jalali date: %d %s %d\n", d, j_month_name[m-1], y);
193 
194  return 0;
195 }
196 #endif
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
time64 gnc_time(time64 *tbuf)
get the current local time
gint64 time64
Definition: gnc-date.h:83