Componente de calendario de tipo copto React Native
Estoy tratando de implementar un calendario no gregoriano que tiene 13 meses. Y había dos funciones que estaba usando para hacer eso. Uno de ellos
generateCalendar se usa para crear una matriz de calendario para cada mes indexado con los días de la semana
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;
}
Y el otro es changeMonth que agrega un mes y cambia el estado creando así una nueva matriz.
function changeMonth(n) {
setState({
activeDate: new Date(state.activeDate.setMonth(state.activeDate.getMonth() + n))
});
}
El problema aquí es que el calendario etíope tiene 13 meses, por lo que no puedo usar setmonth e incrementar o disminuir eso y volver a convertir a etíope porque activeDate determina el número de mes que es 12 para gregorian. Entonces, setmonth se reinicia después de las 11 y solo funciona durante 12 meses
Pero dado que cada mes en el calendario etíope es de 30 días, excepto el último mes que tiene 5 o 6 días, quería hacerlo de modo que recorra los meses al incrementar o disminuir los meses y tal vez luego pueda volver a convertir a gregoriano y establecer el activeDate.
Respuestas
Debe explicar cuáles son las reglas para agregar un mes copto.
Por ejemplo, agregar un mes a las fechas en los meses 1 a 11 puede ser solo agregar 30 días. Para las fechas del mes 12, la adición de 30 días puede hacer que la fecha pase más allá del mes 13, por lo que se convierte en el primer mes del año siguiente. En este caso, ¿debería limitarse la fecha al último día del mes 13? De modo que agregar 1 mes al 30/12/1737 (5 de septiembre de 2021) va al 5/13/1737 en lugar del 25/01/1738 (30 días después).
De manera similar, ¿debería agregar un mes al 1/13/1737 ser 1/01/1738 (es decir, el mismo número del día en el mes siguiente) o 26/01/1738 (30 días después)?
Dada una fecha nativa de ECMAScript, puede agregar un mes copto mediante:
- Obtenga la fecha copta equivalente
- Si el mes copto es del 1 al 11, agregue 30 días
- Si el mes copto es 12, agregue 30 días y si la fecha va más allá del final del mes 13, configúrelo en el último día del mes 13
- Si el mes copto es 13, establezca la fecha en el mismo día del mes siguiente
P.ej
// 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() + ')');
Lo anterior aprovecha Intl.DateTimeFormat y cubre agregar un solo mes, si desea agregar más de uno o agregar años, hay más trabajo por hacer ... En realidad, es solo para demostrar un algoritmo en lugar de proporcionar una función robusta (por ejemplo, getCopticDate probablemente debería ser llamado getCopticDateParts y los valores deben ser números, no cadenas, etc.).