科普特类型日历组件React Native



我正在尝试实现一个有13个月的非公历。我用了两个函数来做这件事。其中一个

generateCalendar用于为每个月创建一个日历矩阵,该矩阵以周天数为索引

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

另一个是changeMonth,它添加了一个月并改变状态,从而创建了一个新的矩阵。

function changeMonth(n) {
setState({
activeDate: new Date(state.activeDate.setMonth(state.activeDate.getMonth() + n))
});
}

这里的问题是埃塞俄比亚日历有13个月,所以我不能使用setmonth和递增或递减来转换回埃塞俄比亚,因为activeDate决定了格雷戈里的月数,即12。因此setmonth在11之后重置,并且仅适用于12个月的

但由于埃塞俄比亚日历中的每个月都是30天,除了最后一个月有5或6天,我想让它在递增或递减月份时循环,然后我可以转换回格里高利语并设置活动日期。

您需要解释添加科普特月的规则。

例如,在第1个月到第11个月的日期中添加一个月可以只添加30天。对于第12个月的日期,增加30天可能会将日期从第13个月推到下一年的第一个月。在这种情况下,日期是否应限制在第13个月的最后一天?因此,将1737年12月30日(2021年9月5日(增加1个月,即为1737年5月13日,而不是1738年1月25日(30天后(。

同样,在1737年1月13日加上一个月是1738年1月1日(即下个月的同一天(还是1738年2月26日(30天后(?

给定本地ECMAScript日期,您可以通过以下方式添加科普特月:

  1. 获取等效的科普特日期
  2. 如果科普特月是1到11,加上30天
  3. 如果科普特月是12,则添加30天;如果日期超过13月底,则将其设置为13月的最后一天
  4. 如果科普特月是13,请将日期设置为下个月的同一天

例如

// 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 isn' +
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 isn' +
printCopticDate(h) + ' (' + h.toDateString() + ')');

上面利用了Intl.DateTimeFormat,涵盖了添加一个月,如果你想添加一个以上或添加年份,还有更多的工作要做……这实际上只是为了演示一个算法,而不是提供一个强大的函数(例如,getCopticDate可能应该被称为getCopticDateParts并且值应该是数字而不是字符串,等等(

最新更新