Last active
December 18, 2015 14:49
-
-
Save behrad/5799941 to your computer and use it in GitHub Desktop.
Jalali Calendar Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% Copyright | |
-module(jalali). | |
-author("jrad <[email protected]>"). | |
-define( G_DAYS_IN_MONTH, [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] ). | |
-define( J_DAYS_IN_MONTH, [ 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 ] ). | |
%% API | |
-export([ | |
gregorian_to_jalali/1, | |
jalali_to_gregorian/1]). | |
gregorian_to_jalali( {{Y,M,D}, {HH,MM,SS}} ) -> | |
{ gregorian_to_jalali( {Y,M,D} ), {HH,MM,SS} }; | |
gregorian_to_jalali( {Y,M,D} ) -> | |
{ GY, GM, GD } = {Y - 1600, M - 1, D - 1}, | |
G_DAY_NO__ = 365*GY+((GY+3) div 4)-((GY+99) div 100)+((GY+399) div 400), | |
G_DAY_NO_ = GD + G_DAY_NO__ + lists:sum( lists:sublist( ?G_DAYS_IN_MONTH, GM ) ), | |
G_DAY_NO = add_leap( G_DAY_NO_, GM, GY ), | |
J_DAY_NO = G_DAY_NO - 79, | |
J_NP = J_DAY_NO div 12053, | |
J_DAY_NO_ = J_DAY_NO rem 12053, | |
JY = 979 + 33*J_NP + 4 * (J_DAY_NO_ div 1461), | |
J_DAY_NO__ = J_DAY_NO_ rem 1461, | |
{J_DAY_NO___, JY_} = extra_years( J_DAY_NO__, JY ), | |
{ I, J_DAY } = for_loop( 0, ?J_DAYS_IN_MONTH, J_DAY_NO___ ), | |
{ JY_, I+1, J_DAY+1 }. | |
jalali_to_gregorian( {{Y,M,D}, {HH,MM,SS}} ) -> | |
{ jalali_to_gregorian( {Y,M,D} ), {HH,MM,SS} }; | |
jalali_to_gregorian( {Y,M,D} ) -> | |
{ JY, JM, JD } = {Y - 979, M - 1, D - 1}, | |
J_DAY_NO__ = 365*JY + (JY div 33)*8 + (((JY rem 33)+3) div 4), | |
J_DAY_NO_ = JD + J_DAY_NO__ + lists:sum( lists:sublist( ?J_DAYS_IN_MONTH, JM ) ), | |
G_DAY_NO = J_DAY_NO_ + 79, | |
GY_ = 1600 + 400 * (G_DAY_NO div 146097), | |
G_DAY_NO_ = G_DAY_NO rem 146097, | |
{G_DAY_NO__, Leap, GYY} = add_leap_j( G_DAY_NO_ ), | |
GY__ = GYY + GY_, | |
GY = GY__ + (4 * (G_DAY_NO__ div 1461)), | |
G_DAY_NO___ = G_DAY_NO__ rem 1461, | |
{G_DAY_NO2, Leap2, GY2} = check_leap_j( G_DAY_NO___, Leap, GY ), | |
{ I, GDN } = for_loop_j( Leap2, 0, ?G_DAYS_IN_MONTH, G_DAY_NO2, get_leap_value(0, Leap2) ), | |
{GY2, I+1, GDN+1 }. | |
check_leap_j( G_DAY_NO, _Leap, GY ) when G_DAY_NO >= 366 -> | |
G_DAY_NO_ = G_DAY_NO-1, | |
{G_DAY_NO_ rem 365, 0, GY+(G_DAY_NO_ div 365) }; | |
check_leap_j( G_DAY_NO, Leap, GY ) -> | |
{G_DAY_NO, Leap, GY }. | |
add_leap_j( G_DAY_NO ) when G_DAY_NO >= 36525 -> | |
G_DAY_NO_ = G_DAY_NO-1, | |
GY = 100 * (G_DAY_NO_ div 36524), | |
G_DAY_NO__ = G_DAY_NO_ rem 36524, | |
if | |
G_DAY_NO__ >= 365 -> {G_DAY_NO__+1, 1, GY}; | |
G_DAY_NO__ < 365 -> {G_DAY_NO__, 0, GY} | |
end; | |
add_leap_j( G_DAY_NO ) -> | |
{G_DAY_NO,1,0}. | |
get_leap_value( I, Leap ) when (I==1) and (Leap==1) -> | |
1; | |
get_leap_value( _I, _Leap ) -> | |
0. | |
for_loop_j( Leap, I, [DAY_NO|Rest], G_DAY_NO, LV ) when (G_DAY_NO >= (DAY_NO+LV)) -> | |
for_loop_j( Leap, I+1, Rest, G_DAY_NO - (DAY_NO+get_leap_value(I, Leap)), get_leap_value(I, Leap) ); | |
for_loop_j( _Leap, I, _, G_DAY_NO, _LV ) -> | |
{I, G_DAY_NO }. | |
for_loop( I, [DAY_NO|Rest], J_DAY_NO ) when (I < 11) and (J_DAY_NO >= DAY_NO) -> | |
for_loop( I+1, Rest, J_DAY_NO - DAY_NO ); | |
for_loop( I, _, J_DAY_NO ) -> | |
{I, J_DAY_NO }. | |
add_leap( G_DAY, GM, GY ) when (GM>1) and ((GY rem 4 == 0) and (GY rem 100 /= 0) ) or (GY rem 400 == 0) -> | |
G_DAY + 1; | |
add_leap( G_DAY, _GM, _GY ) -> | |
G_DAY. | |
extra_years( J_DAY_NO, JY ) when J_DAY_NO >= 366 -> | |
J_DAY = J_DAY_NO-1, | |
{ J_DAY rem 365, JY + (J_DAY div 365) }; | |
extra_years( J_DAY_NO, JY ) when J_DAY_NO < 366 -> | |
{ J_DAY_NO, JY }. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* jalali.js Gregorian to Jalali and inverse date convertor | |
* Copyright (C) 2001 Roozbeh Pournader <[email protected]> | |
* Copyright (C) 2001 Mohammad Toossi <[email protected]> | |
* Copyright (C) 2003,2008 Behdad Esfahbod <[email protected]> | |
* | |
* This program is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License as published by the Free Software Foundation; either | |
* version 2.1 of the License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* You can receive a copy of GNU Lesser General Public License at the | |
* World Wide Web address <http://www.gnu.org/licenses/lgpl.html>. | |
* | |
* For licensing issues, contact The FarsiWeb Project Group, | |
* Computing Center, Sharif University of Technology, | |
* PO Box 11365-8515, Tehran, Iran, or contact us the | |
* email address <[email protected]>. | |
*/ | |
/* Changes: | |
* | |
* 2008-Jul-32: | |
* Use a remainder() function to fix conversion of ancient dates | |
* (before 1600 gregorian). Reported by Shamim Rezaei. | |
* | |
* 2003-Mar-29: | |
* Ported to javascript by Behdad Esfahbod | |
* | |
* 2001-Sep-21: | |
* Fixed a bug with "30 Esfand" dates, reported by Mahmoud Ghandi | |
* | |
* 2001-Sep-20: | |
* First LGPL release, with both sides of conversions | |
*/ | |
g_days_in_month = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); | |
j_days_in_month = new Array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29); | |
function div(a,b) { | |
return Math.floor(a/b); | |
} | |
function remainder(a,b) { | |
return a - div(a,b)*b; | |
} | |
function gregorian_to_jalali(g /* array containing year, month, day*/ ) | |
{ | |
var gy, gm, gd; | |
var jy, jm, jd; | |
var g_day_no, j_day_no; | |
var j_np; | |
var i; | |
gy = g[0]-1600; | |
gm = g[1]-1; | |
gd = g[2]-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; | |
j_day_no = g_day_no-79; | |
j_np = div(j_day_no, 12053); | |
j_day_no = remainder (j_day_no, 12053); | |
jy = 979+33*j_np+4*div(j_day_no,1461); | |
j_day_no = remainder (j_day_no, 1461); | |
if (j_day_no >= 366) { | |
jy += div((j_day_no-1),365); | |
j_day_no = remainder ((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]; | |
} | |
jm = i+1; | |
jd = j_day_no+1; | |
return new Array(jy, jm, jd); | |
} | |
function jalali_to_gregorian(j /* array containing year, month, day*/ ) | |
{ | |
var gy, gm, gd; | |
var jy, jm, jd; | |
var g_day_no, j_day_no; | |
var leap; | |
var i; | |
jy = j[0]-979; | |
jm = j[1]-1; | |
jd = j[2]-1; | |
j_day_no = 365*jy + div(jy,33)*8 + div((remainder (jy, 33)+3),4); | |
for (i=0; i < jm; ++i) | |
j_day_no += j_days_in_month[i]; | |
j_day_no += jd; | |
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 = remainder (g_day_no, 146097); | |
leap = 1; | |
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 = remainder (g_day_no, 36524); | |
if (g_day_no >= 365) | |
g_day_no++; | |
else | |
leap = 0; | |
} | |
gy += 4*div(g_day_no,1461); /* 1461 = 365*4 + 4/4 */ | |
g_day_no = remainder (g_day_no, 1461); | |
if (g_day_no >= 366) { | |
leap = 0; | |
g_day_no--; | |
gy += div(g_day_no, 365); | |
g_day_no = remainder (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); | |
gm = i+1; | |
gd = g_day_no+1; | |
return new Array(gy, gm, gd); | |
} | |
function jalali_today() { | |
Today = new Date(); | |
j = gregorian_to_jalali(new Array( | |
Today.getFullYear(), | |
Today.getMonth()+1, | |
Today.getDate() | |
)); | |
return j[2]+"/"+j[1]+"/"+j[0]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* This file is part of: | |
* Jalali, a Gregorian to Jalali and inverse date convertor | |
* Copyright (C) 2001, 2002 Roozbeh Pournader <[email protected]> | |
* Copyright (C) 2001, 2002 Mohammad Toossi <[email protected]> | |
* | |
* This program is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License as published by the Free Software Foundation; either | |
* version 2.1 of the License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* You can receive a copy of GNU Lesser General Public License at the | |
* World Wide Web address <http://www.gnu.org/licenses/lgpl.html>. | |
* | |
* For licensing issues, contact The FarsiWeb Project Group, | |
* Computing Center, Sharif University of Technology, | |
* PO Box 11365-8515, Tehran, Iran, or contact us the | |
* email address <[email protected]>. | |
*/ | |
/* Changes: | |
* | |
* 2002-Feb-19: | |
* Added PHP header and tailer | |
* 2002-Jan-28: | |
* First LGPL release | |
*/ | |
$g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); | |
$j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29); | |
$j_month_name = array("", "Farvardin", "Ordibehesht", "Khordad", "Tir", | |
"Mordad", "Shahrivar", "Mehr", "Aban", "Azar", | |
"Dey", "Bahman", "Esfand"); | |
function div($a, $b) | |
{ | |
return (int) ($a / $b); | |
} | |
function gregorian_to_jalali($g_y, $g_m, $g_d) | |
{ | |
global $g_days_in_month; | |
global $j_days_in_month; | |
$gy = $g_y-1600; | |
$gm = $g_m-1; | |
$gd = $g_d-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; | |
$j_day_no = $g_day_no-79; | |
$j_np = div($j_day_no, 12053); | |
$j_day_no %= 12053; | |
$jy = 979+33*$j_np+4*div($j_day_no,1461); | |
$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]; | |
} | |
$jm = $i+1; | |
$jd = $j_day_no+1; | |
return array($jy, $jm, $jd); | |
} | |
function farsinum($str) | |
{ | |
if (strlen($str) == 1) | |
$str = "0".$str; | |
$out = ""; | |
for ($i = 0; $i < strlen($str); ++$i) { | |
$c = substr($str, $i, 1); | |
$out .= pack("C*", 0xDB, 0xB0 + $c); | |
} | |
return $out; | |
} | |
function date_format_html($datestamp) | |
{ | |
$tzoffset = 0; | |
list($date,$time) = explode(" ",$datestamp); | |
list($year,$month,$day) = explode("-",$date); | |
list($hour,$minute,$second) = explode(":",$time); | |
$hour = $hour + $tzoffset; | |
list($jyear, $jmonth, $jday) = gregorian_to_jalali($year,$month,$day); | |
$sDate = farsinum($jyear - 1300)."/".farsinum($jmonth)."/".farsinum($jday) | |
." ".farsinum($hour).":".farsinum($minute); | |
return "<span lang='fa' dir='rtl'>" . $sDate . "</span>"; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment