如何在 JavaScript 中将格里高利日期更改为波斯日期?

有人能帮我用 JavaScript 把格里高利日期改成波斯日期吗?我想在 HTML 和 JavaScript 中使用它。

50334 次浏览

You can use the jalaali-js

Jalaali JavaScript

A few javascript functions for converting Jalaali (Jalali, Persian, Khayyami, Khorshidi, Shamsi) and Gregorian calendar systems to each other.

You can also check this out: JalaliJSCalendar (github)

JalaliJSCalendar is a JavaScript date-picker and calendar widget based on "Dynarch DHTML Calendar" from Mihai Bazon. The main difference between two is that JalaliJSCalendar supports Persian (AKA Hijri Shamsi) calendar too, which is the official Iranian calendar.

It contains convertor (jalali.js) and HTML datepicker/calendar

You can use jalali-moment as easy as the following code

import * as moment from 'jalali-moment';
let persianDate = moment("1989/1/24").locale('fa').format('YYYY/M/D'); // 1367/11/4

demo in plunker

getPersianDate = (format) => {
let week = new Array("يكشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنج شنبه", "جمعه", "شنبه")
let months = new Array("فروردين", "ارديبهشت", "خرداد", "تير", "مرداد", "شهريور", "مهر", "آبان", "آذر", "دي", "بهمن", "اسفند");
let today = new Date();
let d = today.getDay();
let day = today.getDate();
let month = today.getMonth() + 1;
let year = today.getYear();
year = (window.navigator.userAgent.indexOf('MSIE') > 0) ? year : 1900 + year;
if (year == 0) {
year = 2000;
}
if (year < 100) {
year += 1900;
}
y = 1;
for (i = 0; i < 3000; i += 4) {
if (year == i) {
y = 2;
}
}
for (i = 1; i < 3000; i += 4) {
if (year == i) {
y = 3;
}
}
if (y == 1) {
year -= ((month < 3) || ((month == 3) && (day < 21))) ? 622 : 621;
switch (month) {
case 1:
(day < 21) ? (month = 10, day += 10) : (month = 11, day -= 20);
break;
case 2:
(day < 20) ? (month = 11, day += 11) : (month = 12, day -= 19);
break;
case 3:
(day < 21) ? (month = 12, day += 9) : (month = 1, day -= 20);
break;
case 4:
(day < 21) ? (month = 1, day += 11) : (month = 2, day -= 20);
break;
case 5:
case 6:
(day < 22) ? (month -= 3, day += 10) : (month -= 2, day -= 21);
break;
case 7:
case 8:
case 9:
(day < 23) ? (month -= 3, day += 9) : (month -= 2, day -= 22);
break;
case 10:
(day < 23) ? (month = 7, day += 8) : (month = 8, day -= 22);
break;
case 11:
case 12:
(day < 22) ? (month -= 3, day += 9) : (month -= 2, day -= 21);
break;
default:
break;
}
}
if (y == 2) {
year -= ((month < 3) || ((month == 3) && (day < 20))) ? 622 : 621;
switch (month) {
case 1:
(day < 21) ? (month = 10, day += 10) : (month = 11, day -= 20);
break;
case 2:
(day < 20) ? (month = 11, day += 11) : (month = 12, day -= 19);
break;
case 3:
(day < 20) ? (month = 12, day += 10) : (month = 1, day -= 19);
break;
case 4:
(day < 20) ? (month = 1, day += 12) : (month = 2, day -= 19);
break;
case 5:
(day < 21) ? (month = 2, day += 11) : (month = 3, day -= 20);
break;
case 6:
(day < 21) ? (month = 3, day += 11) : (month = 4, day -= 20);
break;
case 7:
(day < 22) ? (month = 4, day += 10) : (month = 5, day -= 21);
break;
case 8:
(day < 22) ? (month = 5, day += 10) : (month = 6, day -= 21);
break;
case 9:
(day < 22) ? (month = 6, day += 10) : (month = 7, day -= 21);
break;
case 10:
(day < 22) ? (month = 7, day += 9) : (month = 8, day -= 21);
break;
case 11:
(day < 21) ? (month = 8, day += 10) : (month = 9, day -= 20);
break;
case 12:
(day < 21) ? (month = 9, day += 10) : (month = 10, day -= 20);
break;
default:
break;
}
}
if (y == 3) {
year -= ((month < 3) || ((month == 3) && (day < 21))) ? 622 : 621;
switch (month) {
case 1:
(day < 20) ? (month = 10, day += 11) : (month = 11, day -= 19);
break;
case 2:
(day < 19) ? (month = 11, day += 12) : (month = 12, day -= 18);
break;
case 3:
(day < 21) ? (month = 12, day += 10) : (month = 1, day -= 20);
break;
case 4:
(day < 21) ? (month = 1, day += 11) : (month = 2, day -= 20);
break;
case 5:
case 6:
(day < 22) ? (month -= 3, day += 10) : (month -= 2, day -= 21);
break;
case 7:
case 8:
case 9:
(day < 23) ? (month -= 3, day += 9) : (month -= 2, day -= 22);
break;
case 10:
(day < 23) ? (month = 7, day += 8) : (month = 8, day -= 22);
break;
case 11:
case 12:
(day < 22) ? (month -= 3, day += 9) : (month -= 2, day -= 21);
break;
default:
break;
}
}
if(format===null || format===undefined)
return `${week[d]} ${day} ${months[month - 1]} ${year}`
if(format==="y/m/d")
return `${year}/${month}/${day}`;
if(format==="d/m/y")
return `${day}/${month}/${year}`;
}
console.log(getPersianDate());
console.log(getPersianDate("y/m/d"));
console.log(getPersianDate("d/m/y"));

Get 'jalali.js' from this link.

If your numbers is in Persian format, at first you have to change them to English format, from this link

var
persianNumbers = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g],
arabicNumbers = [/٠/g, /١/g, /٢/g, /٣/g, /٤/g, /٥/g, /٦/g, /٧/g, /٨/g, /٩/g],
fixNumbers = function (str) {
if (typeof str === 'string') {
for (var i = 0; i < 10; i++) {
str = str.replace(persianNumbers[i], i).replace(arabicNumbers[i], i);
}
}
return str;
};

and use such as the function 'getGregorian()' below to convert date. For instance I convert '۱۳۹۸/۰۱/۲۴' date:

function getGregorian () {
var date = ("۱۳۹۸/۰۱/۲۴").split('/');
y = Number( fixNumbers(date[0]) );
m = Number( fixNumbers(date[1]) );
d = Number( fixNumbers(date[2] ));


gDate = toGregorian(y, m, d)
gDate = gDate .gy + '/' + gDate .gm + '/' + gDate .gd;


}

You can use toLocaleDateString();

let today = new Date().toLocaleDateString('fa-IR');
console.log(today);

fa-IR is for Farsi-Iran,

other dates is as follow:

en-US: For English

hi-IN: For Hindi

...

also you can set options as second argument, for example:

let options = { year: 'numeric', month: 'long', day: 'numeric' };
let today = new Date().toLocaleDateString('fa-IR', options);
console.log(today);

and in order to convert characters to Latin digits you can do (as Amir Fo mentioned) :

let today = new Date().toLocaleDateString('fa-IR-u-nu-latn');
console.log(today);

non of answers in this page worked correct, its working in some cases but not always correct! this is working both side converting methods :

function gregorian_to_jalali(gy,gm,gd){
var g_d_m=[0,31,59,90,120,151,181,212,243,273,304,334];
var jy=(gy<=1600)?0:979;
gy-=(gy<=1600)?621:1600;
var gy2=(gm>2)?(gy+1):gy;
var days=(365*gy) +(parseInt((gy2+3)/4)) -(parseInt((gy2+99)/100))
+(parseInt((gy2+399)/400)) -80 +gd +g_d_m[gm-1];
jy+=33*(parseInt(days/12053));
days%=12053;
jy+=4*(parseInt(days/1461));
days%=1461;
jy+=parseInt((days-1)/365);
if(days > 365)days=(days-1)%365;
var jm=(days < 186)?1+parseInt(days/31):7+parseInt((days-186)/30);
var jd=1+((days < 186)?(days%31):((days-186)%30));
return [jy,jm,jd];
}
function jalali_to_gregorian(jy,jm,jd){
var gy=(jy<=979)?621:1600;
jy-=(jy<=979)?0:979;
var days=(365*jy) +((parseInt(jy/33))*8) +(parseInt(((jy%33)+3)/4))
+78 +jd +((jm<7)?(jm-1)*31:((jm-7)*30)+186);
gy+=400*(parseInt(days/146097));
days%=146097;
if(days > 36524){
gy+=100*(parseInt(--days/36524));
days%=36524;
if(days >= 365)days++;
}
gy+=4*(parseInt((days)/1461));
days%=1461;
gy+=parseInt((days-1)/365);
if(days > 365)days=(days-1)%365;
var gd=days+1;
var sal_a=[0,31,((gy%4==0 && gy%100!=0) || (gy%400==0))?29:28,31,30,31,30,31,31,30,31,30,31];
var gm
for(gm=0;gm<13;gm++){
var v=sal_a[gm];
if(gd <= v)break;
gd-=v;
}
return [gy,gm,gd];
}

code from : https://github.com/hat3ck/Persian-Calendar-Qt

To get it in Persian digits:

new Date().toLocaleDateString('fa-IR');
// ۱۳۹۹/۱/۲۳

To get it in Latin digits:

new Date().toLocaleDateString('fa-IR-u-nu-latn');
// 1399/1/23

Mohsen Mentioned this approach in comments, Thanks to him.


Old approach: To get it in Latin digits:

new Date().toLocaleDateString('fa-IR').replace(/([۰-۹])/g, token => String.fromCharCode(token.charCodeAt(0) - 1728));
// 1399/1/23

PersianDate Class

Update: This is a handy and light class that I have written to handle Persian dates:

class PersianDate extends Date {
constructor(...args) {
super(...args);
}


getParts = () => this.toLocaleDateString('fa-IR-u-nu-latn').split("/")
getDay = () => super.getDay() === 6 ? 0 : super.getDay() + 1
getDate = () => this.getParts()[2];
getMonth = () => this.getParts()[1] - 1;
getYear = () => this.getParts()[0];
getMonthName = () => this.toLocaleDateString("fa-IR", { month: 'long' });
getDayName = () => this.toLocaleDateString("fa-IR", { weekday: 'long' });
}

Usage:

let date = new PersianDate();


date.getYear()      // 1399
date.getMonth()     // 1
date.getDate()      // 23
date.getDay()       // 0
date.getDayName()   // شنبه
date.getMonthName() // اردیبهشت


date.getHours()     // 18
date.getMinutes()   // 59
date.getSeconds()   // 30


date.setTime(1469854231000);
date.getYear()      // 1395
date.getMonthName() // مرداد
function convertDate(stringArg) {
const ETF = '۰۱۲۳۴۵۶۷۸۹';
const ans = g2j(...stringArg.split('/').map(elem => +elem))
.map(elem =>
String(elem)
.split('')
.map(subElem => ETF[+subElem])
.join('')
)
.join('/');
return ans;
}

you also can use the following function that returns all options in a JSON. Read more here.

options:
weekday      -> [long | short | narrow]
era          -> [long | short | narrow]
timeZoneName -> [long | short]


year         -> [numeric | 2-digit]
month        -> [numeric | 2-digit | long | short | narrow]
day          -> [numeric | 2-digit]
hour         -> [numeric | 2-digit]
minute       -> [numeric | 2-digit]
second       -> [numeric | 2-digit]


to convert digits to Latin digits
.replace(/([۰-۹])/g, token => String.fromCharCode(token.charCodeAt(0) - 1728));

function PersianDate(raw_date) {
date = new Date(raw_date);
json_date = {
'weekday': {
'long': date.toLocaleDateString('fa-IR', { weekday: 'long' }),
'short': date.toLocaleDateString('fa-IR', { weekday: 'short' }),
'narrow': date.toLocaleDateString('fa-IR', { weekday: 'narrow' }),
},
'era': {
'long': date.toLocaleDateString('fa-IR', { era: 'long' }),
'short': date.toLocaleDateString('fa-IR', { era: 'short' }),
'narrow': date.toLocaleDateString('fa-IR', { era: 'narrow' }),
},
'timeZoneName': {
'long': date.toLocaleDateString('fa-IR', { timeZoneName: 'long' }),
'short': date.toLocaleDateString('fa-IR', { timeZoneName: 'short' }),
},
'year': {
'numeric': date.toLocaleDateString('fa-IR', { year: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { year: '2-digit' }),
},
'month': {
'numeric': date.toLocaleDateString('fa-IR', { month: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { month: '2-digit' }),
'long': date.toLocaleDateString('fa-IR', { month: 'long' }),
'short': date.toLocaleDateString('fa-IR', { month: 'short' }),
'narrow': date.toLocaleDateString('fa-IR', { month: 'narrow' }),
},
'day': {
'numeric': date.toLocaleDateString('fa-IR', { day: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { day: '2-digit' }),
},
'hour': {
'numeric': date.toLocaleDateString('fa-IR', { hour: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { hour: '2-digit' }),
},
'minute': {
'numeric': date.toLocaleDateString('fa-IR', { minute: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { minute: '2-digit' }),
},
'second': {
'numeric': date.toLocaleDateString('fa-IR', { second: 'numeric' }),
'2-digit': date.toLocaleDateString('fa-IR', { second: '2-digit' }),
}
}
return json_date;
}




date = PersianDate(new Date())


// Customize the output format
console.log(date['weekday']['narrow'] + ' ' + date['day']['2-digit'] + ' ' + date['month']['long'] + ' ' + date['year']['numeric']);
// Replatece Farsi digits with Latin ones, e.g. ۲۵ -> 25
console.log(date['day']['2-digit'].replace(/([۰-۹])/g, token => String.fromCharCode(token.charCodeAt(0) - 1728)));

You can install this npm package for node js:

npm i jdate.js

Or import this script for javascript and html:

<script src="https://cdn.jsdelivr.net/npm/jdate.js"></script>

Usage:

var date = new Date();
console.log( date.echoFa() );
console.log( date.echo() );
console.log( date );


~~>    شنبه، 25 دی 1400 - 19:22:22
~~>    Saturday January 15 2022 - 19:22:22
~~>    Sat Jan 15 2022 19:22:22 GMT+0330 (Iran Standard Time)

<script src="https://cdn.jsdelivr.net/npm/jdate.js"></script>
<script type="text/javascript">
(function() {
var date = new Date();
console.log("Normal format: " + date.echo("Y/m/d"));
console.log("Jalali format: " + date.echoFa("Y/m/d"));
})();
</script>