99

Can anyone help me to change Gregorian date to Persian in JavaScript? I want to use it in HTML and JavaScript.

Salek
  • 449
  • 1
  • 10
  • 19
myname
  • 1,159
  • 2
  • 8
  • 9
  • The seems to be your answer ([Link](http://stackoverflow.com/questions/24989984/convert-persian-date-to-julian-or-gregorian-with-keith-wood-calendars)). – CG_FD Feb 23 '16 at 07:18
  • 1
    You can check https://stackoverflow.com/a/54838854/11082300 answer here which solves this. –  Apr 15 '19 at 08:09

12 Answers12

161

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);
Ali_Hr
  • 4,017
  • 3
  • 27
  • 34
  • 10
    `new Date().toLocaleDateString('fa-IR',{year:'numeric',month:'2-digit',day:'2-digit',formatMatcher:'basic'})` – Mahdi Khalili Sep 23 '19 at 06:39
  • 1
    how I reverse that I use your solution but I need to reverse date in last. I mean imagine I have "1398/10/17" and now I need a valid date for the system? – Mostafa Saadatnia Jan 07 '20 at 08:28
  • 3
    @MostafaSaadatnia you should save date and time in timestamp format in database and use this method only for displaying the date and time to persian or other dates. never save this format to database. – Ali_Hr Jan 07 '20 at 08:44
  • Also mind the support of browsers: https://caniuse.com/date-tolocaledatestring , in case of needing a well tested library, i suggest: https://github.com/babakhani/PersianDate – MMMahdy-PAPION Jan 08 '22 at 19:22
  • You can try this method for Converting Persian Dates to any other 18 calendar dates in Javascript: https://stackoverflow.com/questions/24989984/convert-persian-date-to-julian-or-gregorian-with-keith-wood-calendars/71265039#71265039 – Mohsen Alyafei Feb 25 '22 at 11:16
34

PersianDate Class

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

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

    toLocaleDateString = () => super.toLocaleDateString('fa-IR-u-nu-latn');
    getParts = () => this.toLocaleDateString().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: You can use like Date class in js. All of its capabillities are supported.

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() // مرداد
Amir Fo
  • 5,163
  • 1
  • 43
  • 51
  • how replace work? Please explain to me. Tnx – Hosein Feb 06 '22 at 18:05
  • 1
    Every character is an integer number presented in memory, You can refer to ASCII encoding to learn more. Here in the UTF-8 encoding integer value of a Persian numbers' integer value minus 1728 is the Latin integer value of that number. For example Imagine every existing character is a value in an array, The space between Persian numbers and Latin numbers in this array is 1728. @Hosein – Amir Fo Feb 09 '22 at 09:21
  • explained very well. Thanks, bro. – Hosein Feb 09 '22 at 11:22
  • @AmirFo To get it in Latin Digits simply do this by adding the numbering system to use using the `u-nu-` followed by `latn` : `new Date().toLocaleDateString('fa-IR-u-nu-latn')` – Mohsen Alyafei Mar 11 '22 at 06:22
  • @AmirFo also see this method to convert the Persian Dates to over dates: https://stackoverflow.com/questions/71421825/how-to-convert-persian-jalali-dates-to-other-18-calendar-dates-in-javascript-w/71421832?noredirect=1#comment126243822_71421832 – Mohsen Alyafei Mar 11 '22 at 06:23
  • You can try the solution here: https://stackoverflow.com/questions/71421825/how-to-convert-persian-jalali-dates-to-other-18-calendar-dates-in-javascript-w – Mohsen Alyafei Jul 21 '22 at 07:04
  • thank a lot. i use it in typescript for angular and it works perfectly. just is does not need constructor for your PersianDate class – ali pournemat Dec 04 '22 at 19:09
32

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"));
Mehrzad Tejareh
  • 635
  • 5
  • 21
Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
  • 4
    this is not working 1994,09,19 is not 1373/07/27 correct convert is 1373/06/28 – Mahdi Khalili Sep 23 '19 at 06:54
  • Although it's a good code but unfortunately it does not work correctly for some dates like: 1976/05/06 – gyousefi Oct 25 '19 at 18:24
  • 2
    hello Mr.Bashirpour I did some changes to your code if you think this changes is good ... accept my changes. wish you all the best. – Mehrzad Tejareh Oct 05 '20 at 07:12
  • 2
    Hello Mr. Tejareh. Thank you for your good editing. @MehrzadTejareh – Mahdi Bashirpour Oct 05 '20 at 08:28
  • Even the version edited by Mr. Mehrzad Tejareh is not working properly. For example it converts 2021/01/31 to 1399/12/12 which should be 1399/11/12. – Amir Zare Sep 28 '21 at 05:08
  • @MahdiBashirpour Here is my method to convert Persian Dates to any other calendars without external libraries: https://stackoverflow.com/questions/71421825/how-to-convert-persian-jalali-dates-to-other-18-calendar-dates-in-javascript-w/71421832#71421832 – Mohsen Alyafei Mar 10 '22 at 09:51
8

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

fingerpich
  • 8,500
  • 2
  • 22
  • 32
5

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.

Ali Seyedi
  • 1,758
  • 1
  • 19
  • 24
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
4

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

Mahdi Khalili
  • 1,025
  • 15
  • 32
  • Yes Mehdi that's great! Like the second answer (Ali_Hr's answer) works correct for all dates. Thank you! – gyousefi Oct 25 '19 at 18:45
  • 1
    @PureSilence i was using toLocaleDateString until recently, java script toLocaleDateString has problems with persian date on some days of year, that's why i shared this answer its not always correct! but this answer always is correct – Mahdi Khalili Oct 25 '19 at 19:16
  • 2
    Personally I liked your code much more, however, I guess the toLocaleDateString('fa-IR'); is always correct! You can try it event for: new Date('0777/09/09').toLocaleDateString('fa-IR'); which returns 0156/06/18 and your function returns 0156/06/19 and I believe 0156/06/18 is correct! But it's not much important and your function works correct for all newer dates. – gyousefi Oct 26 '19 at 08:09
  • about 0777 you were right this code is not correct about that – Mahdi Khalili Oct 26 '19 at 08:49
  • To do the opposite you can try this method without External Libraries https://stackoverflow.com/questions/71421825/how-to-convert-persian-jalali-dates-to-other-18-calendar-dates-in-javascript-w/71421832#71421832 – Mohsen Alyafei Mar 10 '22 at 14:47
3

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

AHHP
  • 2,967
  • 3
  • 33
  • 41
1

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;

        }
1

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)));
Alin
  • 350
  • 2
  • 13
1

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>
0
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;
}
  • Code-only answers are considered low quality: make sure to provide an explanation what your code does and how it solves the problem. It will help the asker and future readers both if you can add more information in your post. See [Explaining entirely code-based answers](https://meta.stackexchange.com/questions/114762/) – Calos Apr 13 '20 at 00:43
0

Use fa for Intl.DateTimeFormat without any package :

var dateFormat = new Intl.DateTimeFormat("fa",{year:"numeric",month:"2-digit",day:"2-digit"});
console.log(dateFormat.format(Date.now()));

for month name string :

var monthFormat = new Intl.DateTimeFormat("fa",{month:"long"});
console.log(monthFormat.format(Date.now()));

for day of week string :

let dayFormat = new Intl.DateTimeFormat("fa", { weekday: "long" });
console.log(dayFormat.format(Date.now()));
M Komaei
  • 7,006
  • 2
  • 28
  • 34