如何在JavaScript中将公历日期转换为波斯日期?

102

有人能帮我在JavaScript中将公历日期转换为波斯日期吗?我想在HTML和JavaScript中使用它。


这似乎是你的答案(链接)。 - CG_FD
1
你可以在这里查看 https://dev59.com/LlQJ5IYBdhLWcg3wAAxS#54838854 的答案,该答案解决了这个问题。 - user11082300
12个回答

173

您可以使用 toLocaleDateString();

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

fa-IR 是Farsi-Iran的语言代码,

其他语言代码如下:

en-US: 英语

hi-IN: 印地语

...

你也可以将选项作为第二个参数进行设置,例如:

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

为了将字符转换为拉丁数字,可以执行以下操作(如Amir Fo所提到的):

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


10
使用new Date().toLocaleDateString('fa-IR',{year:'numeric',month:'2-digit',day:'2-digit',formatMatcher:'basic'})可以将当前日期转换为格式为年份为数字、月份和日期为两位数字的波斯语(伊朗)格式。 - Mahdi Khalili
1
我如何逆转?我使用了你的解决方案,但我需要反转最后一个日期。我的意思是,假设我有“1398/10/17”,现在我需要系统的有效日期? - Mostafa Saadatnia
3
应该在数据库中以时间戳格式保存日期和时间,并仅在显示日期和时间时使用此方法来转换为波斯语或其他日期格式。不要将此格式保存到数据库中。 - Ali_Hr
同时要关注浏览器的支持情况: https://caniuse.com/date-tolocaledatestring ,如果需要经过充分测试的库,请参考: https://github.com/babakhani/PersianDate - MMMahdy-PAPION
你可以尝试使用这种方法在Javascript中将波斯日期转换为任何其他18个日历日期:https://dev59.com/z4Hba4cB1Zd3GeqPXu7m#71265039 - Mohsen Alyafei

35

波斯日期类

更新:这是一个方便且轻量级的类,我编写了它来处理波斯日期:

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' });
}

使用说明: 您可以像在 JavaScript 中使用 Date 类一样使用。它支持所有功能。

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() // مرداد

如何进行替换操作? 请向我解释一下。 谢谢。 - Hosein
1
每个字符都是在内存中表示的整数,您可以参考ASCII编码以了解更多信息。在UTF-8编码中,波斯数字的整数值减去1728就是该数字的拉丁整数值。例如,想象一下每个现有的字符都是数组中的一个值,在这个数组中,波斯数字和拉丁数字之间的空格为1728。@Hosein - Amir Fo
讲解得非常好。谢谢,兄弟。 - Hosein
@AmirFo 要将其转换为拉丁数字,只需使用“u-nu-”后跟要使用的编号系统,例如 latnnew Date().toLocaleDateString('fa-IR-u-nu-latn') - Mohsen Alyafei
@AmirFo 还可以查看此方法将波斯日期转换为其他日期:https://dev59.com/2MPra4cB1Zd3GeqPquCD#71421832?noredirect=1#comment126243822_71421832 - Mohsen Alyafei
显示剩余2条评论

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"));


4
这不起作用。1994年9月19日不是1373/07/27,正确的转换应该是1373/06/28。 - Mahdi Khalili
虽然这是一段好的代码,但不幸的是它对于某些日期(如1976/05/06)无法正确工作。 - gyousefi
2
你好,Bashirpour先生。 我对你的代码进行了一些更改,如果你认为这些更改不错,请接受我的更改。 祝你一切顺利。 - Mehrzad Tejareh
2
你好,Tejareh先生。感谢您的优秀编辑。@MehrzadTejareh - Mahdi Bashirpour
即使是Mehrzed Tejareh先生编辑的版本也无法正常工作。例如,它将2021/01/31转换为1399/12/12,而实际上应该是1399/11/12。 - Amir Zare
@MahdiBashirpour 这是我用JavaScript将波斯日期转换为其他18种日历的方法,无需使用外部库:https://dev59.com/2MPra4cB1Zd3GeqPquCD#71421832 - Mohsen Alyafei

8
你可以像下面的代码一样轻松使用jalali-moment
import * as moment from 'jalali-moment';
let persianDate = moment("1989/1/24").locale('fa').format('YYYY/M/D'); // 1367/11/4

demo in plunker


5
您可以使用jalaali-js来进行Jalaali(Jalali,波斯,Khayyami,Khorshidi,Shamsi)和Gregorian日历系统之间的转换。这是一些JavaScript函数。

4

这个页面上的所有答案都不正确,有些情况下它可以工作,但并不总是正确的!这个问题在两种转换方法中都存在:

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];
    }

代码来源:https://github.com/hat3ck/Persian-Calendar-Qt


是的,Mehdi,太好了!就像第二个答案(Ali_Hr的答案)对所有日期都有效。谢谢! - gyousefi
1
@PureSilence 直到最近我一直在使用toLocaleDateString,但是JavaScript的toLocaleDateString在某些年份的波斯日期上存在问题,这就是为什么我分享了这个答案,它并不总是正确的!但是这个答案总是正确的。 - Mahdi Khalili
2
个人而言,我更喜欢你的代码,但是我猜toLocaleDateString('fa-IR')总是正确的!你可以尝试一下:new Date('0777/09/09').toLocaleDateString('fa-IR'),它返回0156/06/18,而你的函数返回0156/06/19,我相信0156/06/18才是正确的!但这并不是很重要,你的函数对于所有较新的日期都能正确工作。 - gyousefi
关于0777,你是正确的,这段代码不正确。 - Mahdi Khalili
要做相反的事情,您可以尝试不使用外部库的方法。https://dev59.com/2MPra4cB1Zd3GeqPquCD#71421832 - Mohsen Alyafei

3
你还可以查看这个: JalaliJSCalendar (github)
JalaliJSCalendar是一个基于Mihai Bazon的"Dynarch DHTML Calendar"的JavaScript日期选择器和日历小部件。两者之间的主要区别在于,JalaliJSCalendar还支持波斯语(又称希吉里·沙姆西)日历,这是伊朗官方日历。
它包含转换器(jalali.js)和HTML日期选择器/日历。

2

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()));

月份名称字符串

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

对于星期几字符串

let dayFormat = new Intl.DateTimeFormat("fa", { weekday: "long" });
console.log(dayFormat.format(Date.now()));


1

您可以在Node.js中安装此npm包:

npm i jdate.js

或者导入此JavaScript和HTML脚本:

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

使用方法:

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>


1
您也可以使用以下函数,该函数将以JSON格式返回所有选项。阅读更多此处
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)));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接