(又名波斯历或Jalaali历)是在伊朗和阿富汗使用的阳历。和公历一样,平年365天,闰年366天。伊朗历的元年与伊斯兰历一样,为穆罕默德从麦加前往麦地那的公元622年。伊朗历的一月至六月均有31天,七月至十一月均有30天,十二月有29天(闰年12月有30天)。伊朗历中,每年的第一天在公历的3月份,而由于公历闰年闰在2月29日,而伊朗历闰年闰在其年尾的12月30日,因此平年时,伊朗历的第一天为公历的3月21日,而闰年时的第一天则落在3月20日。
1、伊朗历转公历
参考:伊朗历和公历的换算
第一,如果伊朗历的月份为1-10,则将年份加上621得到公历年份;否则,将年份加上622得到公历年份。
第二,如果伊朗历的月份为1-10,则将月份加上2得到公历月份;否则,将月份减去10得到公历月份。
第三,如果伊朗历的年份加上621后为公历平年,则按下表中平年的部分计算公历日;否则,按照下表中闰年的部分计算公历日:
平年:
第二步中得到的公历月份 | 伊朗历的日期对应加上下列数 |
1 | 20 |
2 | 19 |
3 | 20 |
4 | 20 |
5 | 21 |
6 | 21 |
7 | 22 |
8 | 22 |
9 | 22 |
10 | 22 |
11 | 21 |
12 | 21 |
闰年:
第二步中得到的公历月份 | 伊朗历的日期对应加上下列数 |
1 | 19 |
2 | 18 |
3 | 19 |
4 | 19 |
5 | 20 |
6 | 20 |
7 | 21 |
8 | 21 |
9 | 21 |
10 | 21 |
11 | 20 |
12 | 20 |
伊朗历的日期按照上表加和后,如果得到的结果不超过第一步和第二步计算的公历年月中的天数,则可直接将得到的和作为日期;如果超过,则将得到的和减去第一步和第二步计算的公历年月中的天数作为公历日期,而此时,第二步中得到的公历月份也应加一(如果第二步中得到的公历月份为12,则将第一步得到的公历年份加一,而第二步的公历月份则变为1)。
2、公历转伊朗历
现代波斯历置闰是采取大循环套小循环的方式,2820年分为21个子周期,每个子周期128年,最后一个子周期是132年。每个子周期又分为4个小周期,分别长29年、33年、33年和33年(对于最后一个子周期,是29、33、33、37年)。在29/33/37年长度的小周期内,只要大于1并且被4整除余1的年份即是闰年。
根据 伊朗历转公历 的推算逻辑,反推公历转伊朗历(没有进行大量的测试,只是根据网上对应的日历工具进行简单的测试,大概符合)
参考:https://blog.csdn.net/chenxi365/article/details/5138251
参考:伊朗历_百度百科
QDate convertToPersian(QDate date)
{
int nYear = date.year();
int nMonth = date.month();
int nDay = date.day();
//公历与波斯历每个月份对应的天数差值--以平年为基准
int days[12] = {20,19,20,20,21,21,22,22,22,22,21,21};
//波斯历每个月对应的天数--平年(闰年:12月份为30天)
int persian[12] = {31,31,31,31,31,31,30,30,30,30,30,29};
int iY = 0, iM = 0, iD = 0;
iY = nYear - 621;
if (nMonth >= 3 && nMonth <= 12) iM = nMonth - 2;
else if (nMonth >= 1 && nMonth <= 2) {
iM = nMonth + 10;
iY -= 1;
}
bool bleap = date.isLeapYear(nYear);//判断是否为公历闰年
if (bleap){
iD = nDay - days[nMonth-1] + 1; //转为对应波斯历月份的天数
}
else {
iD = nDay - days[nMonth-1];
}
if (iD < 0) {
iM -= 1;
if (iM <= 0) {
iY -= 1;
iM = 12;
}
}
//计算128年的置润大周期--每128年置31润日--每四年置一润
int nReamin = iY % 128;
bool bflag = false;
if (nReamin > 29) nReamin -= 29; //第一个置润小周期29年
if (nReamin > 33) nReamin -= 33; //第二个置润小周期33年
if (nReamin > 33) nReamin -= 33; //第三个置润小周期33年
if (nReamin > 33) nReamin -= 33; //第四个置润小周期33年
if (nReamin % 4 == 0) bflag = true; //判断是否为波斯历闰年
if (iD < 0) iD = persian[iM-1] + iD; //根据月份和公历差值校正天数
if (iM == 12 && bflag) iD += 1; //闰年12月份为30天,所以需+1
return QDate(iY,iM,iD);
}