// "jalali.cpp" is convertor to and from Gregorian and Jalali calendars.
#include <iostream>
using namespace std;
struct Date{
int yy,mm,dd;
};
Date jalali_to_gregorian(const Date &);
Date gregorian_to_jalali(const Date &);
//test main function
int main()
{
Date a,b;
a.dd=2;
a.mm=4;
a.yy=1366;
b=jalali_to_gregorian(a);
cout<<b.yy<<'-';
cout<<b.mm<<'-';
cout<<b.dd<<endl;
return 0;
}
#define div(x,y) ((x)/(y))
Date jalali_to_gregorian(const Date &j)
{
int i,g_days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
j_days_in_month[] = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
int
jy = j.yy-979,
jm = j.mm-1,
jd = j.dd-1,
j_day_no = 365*jy + div(jy, 33)*8 + div(jy%33+3, 4);
for (i=0; i < jm; ++i)
j_day_no += j_days_in_month[i];
j_day_no += jd;
int
g_day_no = j_day_no+79,
gy = 1600 + 400*div(g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
g_day_no = g_day_no % 146097;
bool leap = true;
if (g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
{
g_day_no--;
gy += 100*div(g_day_no, 36524); /* 36524 = 365*100 + 100/4 - 100/100 */
g_day_no = g_day_no % 36524;
if (g_day_no >= 365)
g_day_no++;
else
leap = false;
}
gy += 4*div(g_day_no, 1461); /* 1461 = 365*4 + 4/4 */
g_day_no %= 1461;
if (g_day_no >= 366) {
leap = false;
g_day_no--;
gy += div(g_day_no, 365);
g_day_no = g_day_no % 365;
}
for (i = 0; g_day_no >= g_days_in_month[i] + (i == 1 && leap); i++)
g_day_no -= g_days_in_month[i] + (i == 1 && leap);
int
gm = i+1,
gd = g_day_no+1;
Date Result;
Result.yy=gy;
Result.dd=gd;
Result.mm=gm;
return Result;
}
Date gregorian_to_jalali(const Date &g)
{
int i,g_days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
j_days_in_month[] = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
int
gy = g.yy-1600,
gm = g.mm-1,
gd = g.dd-1,
g_day_no = 365*gy+div(gy+3,4)-div(gy+99,100)+div(gy+399,400);
for (i=0; i < gm; ++i)
g_day_no += g_days_in_month[i];
if (gm>1 && ((gy%4==0 && gy%100!=0) || (gy%400==0)))
/* leap and after Feb */
g_day_no++;
g_day_no += gd;
int
j_day_no = g_day_no-79,
j_np = div(j_day_no, 12053);/* 12053 = 365*33 + 32/4 */
j_day_no = j_day_no % 12053;
int
jy = 979+33*j_np+4*div(j_day_no,1461); /* 1461 = 365*4 + 4/4 */
j_day_no %= 1461;
if (j_day_no >= 366) {
jy += div(j_day_no-1, 365);
j_day_no = (j_day_no-1)%365;
}
for (i = 0; i < 11 && j_day_no >= j_days_in_month[i]; ++i)
j_day_no -= j_days_in_month[i];
int
jm = i+1,
jd = j_day_no+1;
Date Result;
Result.yy=jy;
Result.mm=jm;
Result.dd=jd;
return Result;
}