Komponen Kalender Jenis Koptik React Native
Saya mencoba menerapkan kalender non-gregorian yang memiliki 13 bulan. Dan ada dua fungsi yang saya gunakan untuk melakukan itu. Salah satu diantara mereka
generateCalendar digunakan untuk membuat matriks kalender untuk setiap bulan yang diindeks dengan hari kerja
function generateCalendar(type = 'en') {
var [etYear, etMonth, etDate] = Ethiopic.toEthiopian(
state.activeDate.getFullYear(),
state.activeDate.getMonth() + 1,
state.activeDate.getDate(),
);
console.log('Month: ', etMonth);
var enYear = state.activeDate.getFullYear();
var enMonth = state.activeDate.getMonth();
var matrix = [];
if (type == 'en') {
matrix = [];
var firstDay = new Date(enYear, enMonth, 1).getDay();
var maxDays = enCalendar.en_days[enMonth];
if (enMonth == 1) {
if ((enYear % 4 == 0 && enYear % 100 != 0) || enYear % 400 == 0) {
maxDays += 1;
}
}
matrix[0] = enCalendar.en_weekDays;
var counter = 1;
for (var row = 1; row < 7; row++) {
matrix[row] = [];
for (var col = 0; col < 7; col++) {
matrix[row][col] = -1;
if (row == 1 && col >= firstDay) {
matrix[row][col] = counter++;
} else if (row > 1 && counter <= maxDays) {
matrix[row][col] = counter++;
}
}
}
} else if (type == 'et') {
matrix = [];
var startDayOfYear = Ethiopic.startDayOfEthiopian(etYear);
// var firstDay = startOfYear + (30 % startDayOfYear);
var firstDayOfYear = new Date(enYear, 8, startDayOfYear).getDay();
var firstDay =
(etMonth - 1) * 2 + firstDayOfYear > 7
? ((etMonth - 1) * 2 + firstDayOfYear) % 7
: (etMonth - 1) * 2 + firstDayOfYear;
var maxDays = etCalendar.et_days[etMonth - 1];
console.log(maxDays);
if (etMonth == 13) {
if (etYear % 4 == 3) {
maxDays += 1;
}
}
matrix[0] = etCalendar.et_weekDays;
var counter = 1;
for (var row = 1; row < 7; row++) {
matrix[row] = [];
for (var col = 0; col < 7; col++) {
matrix[row][col] = -1;
if (row == 1 && col >= firstDay) {
matrix[row][col] = counter++;
} else if (row > 1 && counter <= maxDays) {
matrix[row][col] = counter++;
}
}
}
}
return matrix;
}
Dan yang lainnya adalah changeMonth yang menambahkan satu bulan dan mengubah status sehingga membuat matriks baru.
function changeMonth(n) {
setState({
activeDate: new Date(state.activeDate.setMonth(state.activeDate.getMonth() + n))
});
}
Masalahnya di sini adalah kalender ethiopia memiliki 13 bulan jadi saya tidak dapat menggunakan setmonth dan increment atau decrement dan mengubahnya kembali ke ethiopian karena activeDate menentukan jumlah bulan yaitu 12 untuk gregorian. Jadi setmonth me-reset setelah 11 dan hanya berfungsi selama 12 bulan
Tetapi karena setiap bulan dalam kalender ethiopia adalah 30 hari kecuali bulan terakhir yang memiliki 5 atau 6 hari, saya ingin membuatnya berputar melalui bulan-bulan ketika menambah atau mengurangi bulan dan mungkin kemudian saya dapat mengonversi kembali ke gregorian dan mengatur activeDate.
Jawaban
Anda perlu menjelaskan apa aturan untuk menambahkan bulan Koptik.
Misalnya, menambahkan satu bulan ke tanggal di bulan 1 sampai 11 bisa berarti menambahkan 30 hari. Untuk tanggal di bulan 12, menambahkan 30 hari dapat mendorong tanggal di luar bulan ke-13 hingga bulan pertama tahun berikutnya. Dalam kasus ini, haruskah tanggal dibatasi pada hari terakhir bulan 13? Sehingga menambahkan 1 bulan ke 30/12/1737 (5 Sep 2021) akan menjadi 5/13/1737 bukan 25/01/1738 (30 hari kemudian).
Demikian pula, haruskah menambahkan satu bulan ke 1/13/1737 menjadi 1/01/1738 (yaitu nomor hari yang sama di bulan berikutnya) atau 26/01/1738 (30 hari kemudian)?
Diberikan Tanggal ECMAScript asli, Anda dapat menambahkan bulan Koptik dengan:
- Dapatkan tanggal Koptik yang setara
- Jika bulan Koptik adalah 1 sampai 11, tambahkan 30 hari
- Jika bulan Koptik adalah 12, tambahkan 30 hari dan jika tanggal tersebut melampaui akhir bulan 13, setel ke hari terakhir bulan 13
- Jika bulan Koptik adalah 13, setel tanggal ke hari yang sama di bulan berikutnya
Misalnya
// Given a date, return an object with era, year, month
// and day properties and values for the equivalent
// Coptic date
function getCopticDate(date = new Date()) {
return new Intl.DateTimeFormat(
'en-u-ca-coptic', {
year : 'numeric',
month: '2-digit',
day : '2-digit'
}).formatToParts(date).reduce((acc, part) => {
if (part.type != 'literal') {
acc[part.type] = part.value;
}
return acc;
}, Object.create(null));
}
// Given a Date, return a string for the equivalent
// Coptic date
function printCopticDate(date = new Date()) {
let {era, year, month, day} = getCopticDate(date);
return `${day}/${month}/${year} ${era}`;
}
// Given a Date, return a Date with one Coptic month
// added to to the equivalent Coptic date
function addCopticMonth(date) {
let oDate = new Date(date);
let d = getCopticDate(oDate);
// Add 30 days, then deal with months 12 and 13
oDate.setDate(oDate.getDate() + 30)
// If month was 12 and is now not 13, set to
// last day of 13
let e = getCopticDate(oDate);
if (d.month == '12' && e.month != '13') {
oDate.setDate(oDate.getDate() - e.day);
}
// If month was 13, set to same day in next month
if (d.month == '13') {
oDate.setDate(oDate.getDate() - e.day + +d.day)
}
return oDate;
}
// Some tests
// Add 1 month to today
let d = new Date();
console.log('Today is: ' + printCopticDate(d) +
' (' + d.toDateString() + ')');
let e = addCopticMonth(d);
console.log('+1 month: ' + printCopticDate(e) +
' (' + e.toDateString() + ')');
// Add 1 month to 20/12/1737 -> last day of 13th month
let f = new Date(2021, 7, 26);
let g = addCopticMonth(f);
console.log(printCopticDate(f) + ' (' +
f.toDateString() + ') +1 month is\n' +
printCopticDate(g) + ' (' + g.toDateString() + ')');
// Add 1 month to 05/13/1737 -> same day in first month of next year
let h = addCopticMonth(g);
console.log(printCopticDate(g) + ' (' +
g.toDateString() + ') +1 month is\n' +
printCopticDate(h) + ' (' + h.toDateString() + ')');
Di atas memanfaatkan Intl.DateTimeFormat dan sampul menambahkan satu bulan, jika Anda ingin menambahkan lebih dari satu atau menambahkan tahun, ada lebih banyak pekerjaan yang harus dilakukan… Ini benar-benar hanya untuk mendemonstrasikan algoritma daripada menyediakan fungsi yang kuat (misalnya getCopticDate mungkin harus disebut getCopticDateParts dan nilainya harus berupa angka, bukan string, dll.).