How to Convert any of the 5 Islamic (Hijri) Calendars#39; Dates to any of 18 World Calendars without External Libraries or Complex Astronomical Formulas(如何在没有外部库或复杂天文公式的情况下将5个伊斯兰日历日期中的任何一个转换为18个世界日历中的任何一个) - IT屋-程序员软件
问题描述
在StackOverflow和CodeReview站点上搜索,尚未尝试本问题/帖子中描述的方法;即在不使用外部日期库或使用复杂的数学/天文公式的情况下,将5个伊斯兰日历的日期转换为Java脚本中18个可用日历中的任何一个。
希望此帖子遵守StackOverflowCan I answer my own question?建议的与社区共享新概念代码的策略指南。
我们都知道,Java脚本有一个内置的方法(Intl.DateTimeFormat()),可以将公历日期转换为各种日历的日期(18个世界日历),包括输出字符串的格式。
但是,Java脚本不提供用于反向操作的内置方法,即将18个世界日历日期转换回公历日期(包括伊斯兰日历日期)或其他日历。为此,您将需要使用外部日期库来执行转换,如‘Moment.js’和许多其他文件。
此处使用的方法/代码不使用外部库,而是使用按目标近似方法进行的Java日历转换。下面的流程图总结了可用于将其他日历转换为剩余日历的方法的概念。
下面的短Java脚本函数提供了将五(5)个伊斯兰(Hijri)日历的任何日期(从伊斯兰年份280,803 AH到+281,510 AH)转换为以下18个Java日历中的任何一个的功能,并提供了用于格式化结果输出的选项: 该方法不使用外部库,也不使用复杂的数学或天文公式,并且仅依赖于基于ICU代码[https://icu.unicode.org/]. 此方法可确保输出始终准确,并与Java引擎输出完全兼容。 虽然一些外部库非常好,但随着时间的推移,它们往往会失去更新和支持;'moment.js' library的最近案例就是一个例子。 函数语法为: 在其最简单的形式中,该函数默认为转换 它还将默认使用ISO日期格式转换为 示例:将伊斯兰日期21 Rajab 1443(即21/07/1443)转换为公历。 TO将伊斯兰日期转换为另一个日历(如‘波斯历’): 若要向输出添加格式,请使用 示例:使用完整日期样式将伊斯兰日期转换为波斯日期 示例:使用阿拉伯语区域设置将伊斯兰日期转换为希伯来语 可以对所有其他18个日历执行上述操作。 新增功能是能够将伊斯兰日期格式设置为可用 为此,指定 示例:使用波斯语区域设置设置伊斯兰日期的格式 示例:在印地语区域设置伊斯兰日期格式 默认输入的伊斯兰日历为 示例:将 您可以从上面看到 您可以使用 如果将无效的伊斯兰日期传递给该函数,将生成错误 无效的伊斯兰日期是指月份中的日期不正确,或者日期或月份不正确。 例如,伊斯兰日期1443/2/30无效,因为回历(月份和月份)的第二个月始终是29天,而不能是30天。 此外,例如,伊斯兰日期1442/12/30将引发错误,因为1442年是非闰年,而12月只有29天。 如果您认为内部的Java脚本ICU代码是可靠和准确的,则此方法仅使用从Java引擎内部生成的数据。无需担心外部不正确的数学运算或代码中的错误/错误,除非它们位于Java引擎本身内部。 下面是包含用于转换和格式化的示例测试用例的函数,可以运行和测试。 举例说明如何将伊斯兰日期(1443/7/21)恰好是今天的日期转换为所有其他日历格式。 如有任何改进/建议/替代方案,欢迎光临。Java脚本Intl.DateTimeFormat()
"buddhist", "chinese", "coptic", "dangi", "ethioaa", "ethiopic", "gregory", "hebrew", "indian", "islamic", "islamic-umalqura", "islamic-tbla", "islamic-civil", "islamic-rgsa", "iso8601", "japanese", "persian", "roc", "islamicc".
语法
hijriToCalendars(year, month, day, [options])
'islamic-umalqura'
日历,该日历是最常用和最近使用的伊斯兰日历。Gregorian
日历。hijriToCalendars(1443,7,21);
output: 2022-02-22T00:00:00.000Z // default output Gregorian ISO format
hijriToCalendars(1443,7,21, { toCal: "persian" });
output: 12/3/1400 AP
'dateStyle'
选项,就像在Java脚本Intl.DateTimeFormat()
方法中一样。 hijriToCalendars(1443,7,21, { toCal: "persian", dateStyle: "full" });
output: Tuesday, Esfand 3, 1400 AP
hijriToCalendars(1443,7,21,{ toCal:"hebrew", dateStyle: "full", locale:"ar"})
output: الثلاثاء، ٢١ آذار الأول ٥٧٨٢ ص
'dateStyles'
和'locales'
中的任何一个,而无需转换。'toCal'
与伊斯兰输入日历相同,默认使用:'islamic-umalqura'
。 hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"fa"}));
output: سهشنبه ۲۱ رجب ۱۴۴۳ ه.ق. // mind the RTL requirements
hijriToCalendars(1443,7,21,{ toCal : "islamic-umalqura", dateStyle : "full", locale : "hi"}));
output: AH मंगलवार, 21 रजब 1443
'islamic-umalqura'
,但是,您可以使用'fromCal'
选项将其更改为五(5)个伊斯兰日历中的任何一个。Islamic-Civil
日期21 Rajab 1443(即21/07/1443)转换为格里高利。 hijriToCalendars(1443,7,21, {fromCal : "islamic-civil" });
output: 2022-02-23T00:00:00.000Z
islamic-civil
日期与islamic-umalqura
日期相差1天。Intl.DateTimeFormat()
中的所有可用选项设置输出日期的格式。无效的伊斯兰日期
Invalid islamic-xxxxx date!
。此方法可靠、准确吗?
/**********************************************************************************
* @function : hijriToCalendars(year, month, day, [options])
*
* @purpose : Converts Islamic (Hijri) Date to other Calendars' Dates.
* Handles Hijri dates from -280,803 AH to +281,510 AH.
* Handles all 5 Islamic Calendar Types.
* Uses the 'JS Calendar Conversion by Target Approximation' Method.
* No external libraries or complex mathematical/astronomical formulas.
*
* @version : 1.00
* @author : Mohsen Alyafei
* @date : 21 Feb 2022
* @licence : MIT
* @param : year : (numeric) [required] Hijri year (-280803 to 281510)
* @param : month : (numeric) [required] hijri month (1 to 12) note: months is standard 1 based
* @param : day : (numeric) [required] hijri day (1 to 29/30)
* @param : options: Object with the following optional parameters:
*
* 'fromCal': Specifies the the type of input Islamic Calendar with 5 options:
* - 'islamic-umalqura' (default)
* - 'islamic-civil'
* - 'islamic-tbla'
* - 'islamic-rgsa'
* - 'islamic'
*
* 'toCal' : Specifies the the type of output Calendar to convert to with 19 Calendars:
* - "gregory" : (default)
* - "buddhist", "chinese", "coptic", "dangi", "ethioaa", "ethiopic",
* "hebrew", "indian", "islamic", "islamic-umalqura", "islamic-tbla",
* "islamic-civil", "islamic-rgsa", "iso8601", "japanese", "persian", "roc".
*
* 'dateStyle' Same as used in the Intl.DateTimeFormat() constructor.
* If not stated, default output is in Gregorian ISO Format: YYYY:MM:DDTHH:mm:ss.sssZ
*
* 'locale' The BCP 47 language tag for formatting (default is 'en').
*
* Other options: As used in the Intl.DateTimeFormat() constructor.
*
* @returns : Return the date in the calendar and format of the specified options.
***********************************************************************************/
//**********************************************************************************
function hijriToCalendars(year, month, day, op={}) {
op.fromCal ??= "islamic-umalqura"; //
let gD = new Date(Date.UTC(2000,0,1));
gD = new Date(gD.setUTCDate(gD.getUTCDate() +
~~(227022+(year+(month-1)/12+day/354)*354.367)));
const gY = gD.getUTCFullYear(gD)-2000,
dFormat = new Intl.DateTimeFormat('en-u-ca-' + op.fromCal, {dateStyle:'short', timeZone:'UTC'});
gD = new Date(( gY < 0 ? "-" : "+")+("00000" + Math.abs(gY)).slice(-6)+"-"+("0" + (gD.getUTCMonth(gD)+1)).slice(-2)+"-" + ("0" + gD.getUTCDate(gD)).slice(-2));
let [iM,iD,iY]= [...dFormat.format(gD).split("/")], i=0;
gD = new Date(gD.setUTCDate(gD.getUTCDate() +
~~(year*354+month*29.53+day-(iY.split(" ")[0]*354+iM*29.53+iD*1)-2)));
while (i < 4) {
[iM,iD,iY] = [...dFormat.format(gD).split("/")];
if (iD == day && iM == month && iY.split(" ")[0] == year) return formatOutput(gD);
gD = new Date(gD.setUTCDate(gD.getUTCDate()+1)); i++;
}
throw new Error("Invalid "+op.fromCal+" date!");
function formatOutput(gD){
return "toCal"in op ? (op.calendar= op.toCal,
new Intl.DateTimeFormat(op.locale ??= "en", op).format(gD)) : gD;
}
}
//**********************************************************************************
//==========================================================
// Test Units
//==========================================================
console.log("=".repeat(60));
console.log("Convert the Hijri (Islamic) Date '1443-07-21' to other calendars:");
console.log("input to function ==>: hijriToCalendars(1443,7,21, option)");
console.log("=".repeat(60));
console.log("Default (Gregory) ISO format : ",hijriToCalendars(1443,7,21)); // convert default islamic-umalqura date to default gregorian date
console.log("Gregory 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"gregory",dateStyle:"full"}));
console.log("Persian no format : ",hijriToCalendars(1443,7,21,{toCal:"persian"}));
console.log("Persian 'medium' format : ",hijriToCalendars(1443,7,21,{toCal:"persian",dateStyle:"medium"}));
console.log("Persian 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"persian",dateStyle:"full"}));
console.log("Persian 'full' format 'fa' locale: ",hijriToCalendars(1443,7,21,{toCal:"persian",dateStyle:"full",locale:"fa"}));
console.log("Hebrew no format : ",hijriToCalendars(1443,7,21,{toCal:"hebrew"}));
console.log("Hebrew 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"hebrew",dateStyle:"full"}));
console.log("Hebrew 'full' format 'ar' locale : ",hijriToCalendars(1443,7,21,{toCal:"hebrew",dateStyle:"full",locale:"ar"}));
console.log("Indian no format : ",hijriToCalendars(1443,7,21,{toCal:"indian"}));
console.log("Indian 'medium' format : ",hijriToCalendars(1443,7,21,{toCal:"indian",dateStyle:"medium"}));
console.log("Indian 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"indian",dateStyle:"full"}));
console.log("Indian 'full' format 'hi' locale : ",hijriToCalendars(1443,7,21,{toCal:"indian",dateStyle:"full",locale:"hi"}));
console.log("Indian 'full' format 'in' locale : ",hijriToCalendars(1443,7,21,{toCal:"indian",dateStyle:"full",locale:"in"}));
console.log("Chinese no format : ",hijriToCalendars(1443,7,21,{toCal:"chinese"}));
console.log("Chinese 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"chinese",dateStyle:"full"}));
console.log("Chinese 'full' format 'zh' locale: ",hijriToCalendars(1443,7,21,{toCal:"chinese",dateStyle:"full",locale:"zh-CN"}));
console.log("Coptic 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"coptic",dateStyle:"full"}));
console.log("Coptic 'full' format 'ar' locale : ",hijriToCalendars(1443,7,21,{toCal:"coptic",dateStyle:"full",locale:"ar"}));
console.log("Dangi (Korean) 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"dangi",dateStyle:"full"}));
console.log("R.O.C. (Minguo) 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"roc",dateStyle:"full"}));
console.log("Japanese 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"japanese",dateStyle:"full"}));
console.log("Ethioaa 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"ethioaa",dateStyle:"full"}));
console.log("Ethiopic 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"ethiopic",dateStyle:"full"}));
console.log("Buddhist 'full' format : ",hijriToCalendars(1443,7,21,{toCal:"buddhist",dateStyle:"full"}));
//console.log("");
console.log("=".repeat(60));
console.log("Format the input Hijri Date in different locales without conversion:");
console.log("=".repeat(60));
console.log("Islamic-umalqura 'ar' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"ar"}));
console.log("Islamic-umalqura 'en' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"en"}));
console.log("Islamic-umalqura 'fa' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"fa"}));
console.log("Islamic-umalqura 'hi' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"hi"}));
console.log("Islamic-umalqura 'id' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"id"}));
console.log("Islamic-umalqura 'pa' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"pa"}));
console.log("Islamic-umalqura 'ma' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-umalqura",dateStyle:"full", locale:"ma"}));
console.log("Islamic-cvil 'ar' locale : ",hijriToCalendars(1443,7,21,{toCal:"islamic-civil",dateStyle:"full", locale:"ar"}));
//console.log("");
console.log("=".repeat(60));
console.log("Convert Max Negative and Max Positive Hijri Dates to Gregorian");
console.log("=".repeat(60));
console.log("Maximum Negative Date : ",hijriToCalendars(-280803,12,22)); // max negative hijri date
console.log("Maximum Positive Date : ",hijriToCalendars(281510,12,29)); // max positive hijri date
//console.log("=".repeat(60));
// Other Test Cases
var r=0; // test tracker
r |= test(1,1,1,{},"0622-07-19T00:00:00.000Z");
r |= test(622,7,18,{},"1225-08-02T00:00:00.000Z");
r |= test(1443,7,21,{},"2022-02-22T00:00:00.000Z");
r |= test(1443,7,14,{},"2022-02-15T00:00:00.000Z");
r |= test(1443,9,1,{},"2022-04-02T00:00:00.000Z");
r |= test(2000,9,1,{},"2562-09-01T00:00:00.000Z");
r |= test(2100,9,1,{},"2659-09-10T00:00:00.000Z");
r |= test(2200,9,1,{},"2756-09-17T00:00:00.000Z");
r |= test(2300,9,1,{},"2853-09-25T00:00:00.000Z");
r |= test(2400,9,1,{},"2950-10-04T00:00:00.000Z");
r |= test(2443,9,1,{},"2992-06-22T00:00:00.000Z");
r |= test(3443,9,1,{},"3962-09-13T00:00:00.000Z");
r |= test(4443,9,1,{},"4932-12-03T00:00:00.000Z");
r |= test(5443,9,1,{},"5903-02-23T00:00:00.000Z");
r |= test(6443,9,1,{},"6873-05-14T00:00:00.000Z");
r |= test(6550,7,14,{},"6977-01-20T00:00:00.000Z");
r |= test(7443,9,1,{},"7843-08-05T00:00:00.000Z");
r |= test(8443,9,1,{},"8813-10-24T00:00:00.000Z");
r |= test(9443,9,1,{},"9784-01-14T00:00:00.000Z");
r |= test(10443,9,1,{},"+010754-04-06T00:00:00.000Z");
r |= test(150443,9,1,{},"+146585-06-23T00:00:00.000Z");
r |= test(1443,4,29,{fromCal:"islamic"},"2021-12-03T00:00:00.000Z");
r |= test(1443,7,21,{fromCal:"islamic-civil"},"2022-02-23T00:00:00.000Z");
r |= test(1443,7,21,{fromCal:"islamic"},"2022-02-22T00:00:00.000Z");
r |= test(102428,4,29,{fromCal:"islamic-civil"},"+099999-11-24T00:00:00.000Z");
r |= test(-640, 7, 20,{fromCal:"islamic-civil"},"0001-03-03T00:00:00.000Z");
r |= test(-2000,1,1,{},"-001319-02-16T00:00:00.000Z");
r |= test(-2020,1,1,{},"-001339-09-22T00:00:00.000Z");
r |= test(-6000,1,1,{fromCal:"islamic-tbla"},"-005200-03-27T00:00:00.000Z");
r |= test(-6000,1,1,{fromCal:"islamic-rgsa"},"-005200-03-24T00:00:00.000Z");
r |= test(-20000,1,1,{},"-018783-02-11T00:00:00.000Z");
r |= test(-60000,12,29,{fromCal:"islamic"},"-057591-02-03T00:00:00.000Z");
r |= test(-100000,12,20,{fromCal:"islamic"},"-096400-02-08T00:00:00.000Z");
r |= test(-116000,1,1,{},"-111925-09-16T00:00:00.000Z");
r |= test(-270000,12,29,{fromCal:"islamic"},"-261338-01-15T00:00:00.000Z");
r |= test(275000,12,29,{fromCal:"islamic"},"+267434-02-27T00:00:00.000Z");
r |= test(-200000,1,1,{},"-193424-12-23T00:00:00.000Z");
r |= test(-206779,3,1,{},"-200000-01-01T00:00:00.000Z");
if (r==0) console.log("✅ All Other Test Cases Passed.");
//============ test function ============
function test(Y,M,D,OP,should) {
let out = hijriToCalendars(Y,M,D,OP);
out=out.toISOString();
if (out !== should) {console.log(`${Y},${M},${D} Output : ${out}
${Y},${M},${D} Should be: ${should}`);return 1;}
}
按目标近似法进行的Java日历转换-流程图
推荐答案
工程师、物理学家和数学家在一列穿过英国乡村的火车上,当工程师向窗外望去,看到山坡上有一只孤零零的害群之马时,喊道,嘿,看哪,英格兰有害群之马!物理学家很快警告他,我们所能确定的是,英格兰有一只害群之马。数学家于是告诫他们两人,宣布,我们所能得出的结论是,英格兰至少有一只黑羊在一边……
由于我是一名数学家,我在欠款方面表示歉意...
经过研究,我认为长期的答案在于ECMAScript提案"Temporal",目前(截至2022年2月24日)在Active Proposals的Stage 3中。全文Stage 3 Draft of the Temporal proposal提供了关于提案动机的一些背景知识以及整个技术规范,Temporal documentation提供了更容易理解的目的和操作用途。后面的文档是一个很好的起点...
从文档中摘录的几位知名人士:
Temporal.Instant抽象时间点,而不考虑日历或位置。即,这是所有日历和时区必须引用以在指定区域设置中呈现日期和时间的绝对时间。
Temporal.Calendar是日历系统的表示,它提供有关日历的细节和操作日历的方法。存在许多预置日历,例如‘Gregory’、‘Islamic’、‘Hebrew’等。此外,时间建议还使实现您自己的日历成为可能。
作为ECMAScript阶段3的提议,时态仍然处于实验阶段,但鼓励在非生产环境中进行测试,并报告任何错误。由于Temporal.Instant
是与日历或位置无关的基本时间点,因此日历之间的转换是通过不同日历显示Temporal.Instant
的自然结果。
<script type='module'>
import * as TemporalModule from 'https://cdn.jsdelivr.net/npm/@js-temporal/polyfill@0.3.0/dist/index.umd.js'
const Temporal = temporal.Temporal;
let islamicDate = Temporal.ZonedDateTime.from( {
year: 1440,
monthCode: 'M06',
day: 2,
hour:12,
minute: 45,
timeZone: 'Asia/Dubai',
calendar: 'islamic'
} );
let hebrewDate = Temporal.ZonedDateTime.from( islamicDate ).withCalendar( 'hebrew' );
let gregoryDate = Temporal.ZonedDateTime.from( islamicDate ).withCalendar( 'gregory' );
console.log( `Date in Islamic: ${ islamicDate.toPlainDate().toLocaleString( 'en-US', { calendar: 'islamic' } ) }` );
console.log( `DateTime in Islamic in Dubai: ${ islamicDate.toLocaleString( 'en-US', { calendar: 'islamic' } ) }` );
console.log( `DateTime in Islamic in London: ${ islamicDate.toInstant().toZonedDateTimeISO( 'Europe/London' ).toLocaleString('en-US', { calendar: 'islamic' } ) }` );
console.log( `Date in Hebrew: ${ hebrewDate.toPlainDate().toLocaleString( 'en-US', { calendar: 'hebrew' } ) }` );
console.log( `DateTime in Hebrew in Dubai: ${ hebrewDate.toLocaleString( 'en-US', { calendar: 'hebrew' } ) }` );
console.log( `DateTime in Hebrew in London: ${ hebrewDate.toInstant().toZonedDateTimeISO( 'Europe/London' ).toLocaleString('en-US', { calendar: 'hebrew' } ) }` );
console.log( `Date in Gregorian: ${ gregoryDate.toPlainDate().toLocaleString( 'en-US' ) }` );
console.log( `DateTime in Gregorian: ${ gregoryDate.toLocaleString( 'en-US' ) }` );
console.log( `Islamic Date in English (United States) Locale:
${ islamicDate.toPlainDate().toString() }` );
console.log( `Islamic DateTime in English (United States) Locale:
${ islamicDate.toString() }` );
</script>
(更新了代码段以更好地演示时区和日历之间的转换,以及显示日期的各种方法。)
这篇关于如何在没有外部库或复杂天文公式的情况下将5个伊斯兰日历日期中的任何一个转换为18个世界日历中的任何一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在没有外部库或复杂天文公式的情况下将5个伊斯兰日历日期中的任何一个转换为18个世界日历中的任何一个
基础教程推荐
- 角度Apollo设置WatchQuery结果为可用变量 2022-01-01
- 在for循环中使用setTimeout 2022-01-01
- 当用户滚动离开时如何暂停 youtube 嵌入 2022-01-01
- 响应更改 div 大小保持纵横比 2022-01-01
- 悬停时滑动输入并停留几秒钟 2022-01-01
- Karma-Jasmine:如何正确监视 Modal? 2022-01-01
- 有没有办法使用OpenLayers更改OpenStreetMap中某些要素 2022-09-06
- 在 JS 中获取客户端时区(不是 GMT 偏移量) 2022-01-01
- 我什么时候应该在导入时使用方括号 2022-01-01
- 动态更新多个选择框 2022-01-01