Koptische Kalenderkomponente React Native
Ich versuche, einen nicht-gregorianischen Kalender mit 13 Monaten zu implementieren. Und dafür habe ich zwei Funktionen verwendet. Einer von ihnen
generateCalendar wird verwendet, um eine Kalendermatrix für jeden Monat zu erstellen, der mit den Wochentagen indiziert ist
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;
}
Und das andere ist changeMonth, das einen Monat hinzufügt und den Status ändert, wodurch eine neue Matrix erstellt wird.
function changeMonth(n) {
setState({
activeDate: new Date(state.activeDate.setMonth(state.activeDate.getMonth() + n))
});
}
Das Problem hierbei ist, dass der äthiopische Kalender 13 Monate hat, daher kann ich setmonth nicht verwenden und das inkrementieren oder dekrementieren und wieder in äthiopisch konvertieren, da das activeDate die Anzahl der Monate bestimmt, die für gregorian 12 sind. Setmonth wird also nach 11 zurückgesetzt und funktioniert nur 12 Monate
Aber da jeder Monat im äthiopischen Kalender 30 Tage beträgt, mit Ausnahme des letzten Monats mit 5 oder 6 Tagen, wollte ich ihn so gestalten, dass er die Monate durchläuft, wenn Monate erhöht oder verringert werden, und vielleicht kann ich dann wieder auf gregorian umstellen und den einstellen activeDate.
Antworten
Sie müssen die Regeln für das Hinzufügen eines koptischen Monats erläutern.
Wenn Sie beispielsweise Daten in den Monaten 1 bis 11 um einen Monat erweitern, können Sie lediglich 30 Tage hinzufügen. Bei Daten im 12. Monat kann das Hinzufügen von 30 Tagen das Datum über den 13. Monat hinaus in den ersten Monat des folgenden Jahres verschieben. Sollte in diesem Fall das Datum auf den letzten Tag des Monats 13 begrenzt werden? Das Hinzufügen von 1 Monat zum 30.12.1737 (5. September 2021) erfolgt also zum 13.05.1737 und nicht zum 25.01.1738 (30 Tage später).
Sollte das Hinzufügen eines Monats zum 13.01.1737 ebenfalls der 01.01.1738 (dh die Nummer des gleichen Tages im folgenden Monat) oder der 26.01.1738 (30 Tage später) sein?
Bei einem nativen ECMAScript-Datum können Sie einen koptischen Monat hinzufügen, indem Sie:
- Holen Sie sich das entsprechende koptische Datum
- Wenn der koptische Monat 1 bis 11 ist, fügen Sie 30 Tage hinzu
- Wenn der koptische Monat 12 ist, fügen Sie 30 Tage hinzu, und wenn das Datum über das Ende des Monats 13 hinausgeht, setzen Sie es auf den letzten Tag des Monats 13
- Wenn der koptische Monat 13 ist, setzen Sie das Datum auf den gleichen Tag im folgenden Monat
Z.B
// 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() + ')');
Das Obige nutzt Intl.DateTimeFormat und deckt das Hinzufügen eines einzelnen Monats ab. Wenn Sie mehr als einen oder mehrere Jahre hinzufügen möchten, ist mehr Arbeit zu erledigen. Es geht eigentlich nur darum, einen Algorithmus zu demonstrieren, anstatt eine robuste Funktion bereitzustellen (z. B. sollte getCopticDate wahrscheinlich sein genannt getCopticDateParts und die Werte sollten Zahlen nicht Strings, etc.).