当前位置:网站首页>【微信小程序】农历公历互相转换
【微信小程序】农历公历互相转换
2022-07-27 09:14:00 【xun-ming】
需求来源
之前写了一篇获取农历日期的文章,【微信小程序】获取农历及星期,后来想到我这个小程序【TimeAssistant】中的“远离工作”功能模块还得优化,具体功能界面如下图

此功能原来做法是把节假日日期固定写在代码里,这样做的话很不灵活,每年都得至少更新一次版本,如果能让这个日期动态获取,这样岂不是更好。
考虑到这里面几个节日都是跟农历相关,比如中秋、端午、春节,所以就想到写一个方法,传入农历日期获取公历日期
实战代码
核心方法
/** * 根据农历获取阳历 * @see https://blog.csdn.net/zhangjiaqianghh/article/details/115478404 * @param {农历日期, 2022-01-01} lunar * @param {是否闰月, false} leapMonthFlag * @return {阳历日期, 2022-02-01} newDate */
const getSolarByLunar = (lunar,leapMonthFlag) => {
// 使用//g正则替换所有
var lunarDt = lunar.replace(/-/g,'');
var lunarYear = parseInt(lunarDt.substring(0, 4));
var lunarMonth = parseInt(lunarDt.substring(4, 6));
var lunarDay = parseInt(lunarDt.substring(6, 8));
checkLunarDate(lunarYear, lunarMonth, lunarDay, leapMonthFlag);
var offset = 0;
for (var i = 1900; i < lunarYear; i++) {
var yearDaysCount = getYearDays(i); // 求阴历某年天数
offset += yearDaysCount;
}
var leapMonth = getLeapMonth(lunarYear);
//当年没有闰月或月份早于闰月或和闰月同名的月份
if (leapMonth == 0 || (lunarMonth < leapMonth) || (!leapMonthFlag & lunarMonth == leapMonth)) {
for (var i = 1; i < lunarMonth; i++) {
var tempMonthDaysCount = getMonthDays(lunarYear, i);
offset += tempMonthDaysCount;
}
// 检查日期是否大于最大天
if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
console.error('不合法的农历日期!')
}
offset += lunarDay; // 加上当月的天数
}else{
console.log("当年有闰月,且月份晚于或等于闰月======" + leapMonth);
//当年有闰月,且月份晚于或等于闰月
for (var i = 1; i < lunarMonth; i++) {
var tempMonthDaysCount = getMonthDays(lunarYear, i);
offset += tempMonthDaysCount;
}
if (lunarMonth > leapMonth) {
var temp = getLeapMonthDays(lunarYear); // 计算闰月天数
offset += temp; // 加上闰月天数
if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
throw (new Exception("不合法的农历日期!"));
}
offset += lunarDay;
} else {
// 如果需要计算的是闰月,则应首先加上与闰月对应的普通月的天数
// 计算月为闰月
var temp = getMonthDays(lunarYear, lunarMonth); // 计算非闰月天数
offset += temp;
if (lunarDay > getLeapMonthDays(lunarYear)) {
throw (new Exception("不合法的农历日期!"));
}
offset += lunarDay;
}
}
// 阳历日期计算起点
var startStr = '1900-01-30';
var newDate =new Date(startStr);
newDate.setDate(newDate.getDate() + offset);
// console.log("测试1======" + getZeroDate(newDate) +getWeekByDate(newDate));
return newDate;
}
/** * 根据阳历获取农历 * @see https://www.iteye.com/blog/lixor-1190599 * @param {当前日期} curDate * @returns {int数组 [1,2]} result:索引1代表天数,索引2代表月份 */
const getLunarBySolar = curDate => {
var leapMonth = 0;
var date = new Date('1900/1/31');
// 求出当前时间和1900年1月31日相差的天数
var offset = parseInt( (curDate.getTime() - date.getTime()) / 86400000 );
// 用offset减去每农历年的天数,计算当天是农历第几天,i最终结果是农历的年份,offset是当年的第几天
var iYear, daysOfYear = 0;
for (iYear = 1900; iYear < 2100 && offset > 0; iYear++) {
daysOfYear = getYearDays(iYear);
offset -= daysOfYear;
}
if (offset < 0) {
offset += daysOfYear;
iYear--;
}
// 闰哪个月,1-12
leapMonth = getLeapMonth(iYear);
var leap = false; // 默认值
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
var iMonth, daysOfMonth = 0;
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
// 闰月
if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
--iMonth;
leap = true;
daysOfMonth = getLeapMonthDays(iYear);
} else
daysOfMonth = getMonthDays(iYear, iMonth);
offset -= daysOfMonth;
// 解除闰月
if (leap && iMonth == (leapMonth + 1))
leap = false;
}
// offset为0时,并且刚才计算的月份是闰月,要校正
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
if (leap) {
leap = false;
} else {
leap = true;
--iMonth;
}
}
// offset小于0时,也要校正
if (offset < 0) {
offset += daysOfMonth;
--iMonth;
}
var result = [];
result.push(chineseNumber[iMonth - 1]);
result.push(getChinaDayString(offset + 1));
return result;
}
运行效果
以下为上面两个方法实测日志图

工具方法
1、检查农历日期是否有问题
const checkLunarDate = (lunarYear,lunarMonth,lunarDay,leapMonthFlag) =>{
if(lunarYear < 1900 || lunarYear > 2100){
console.error("非法年份" + lunarYear);
}
if(lunarMonth < 1 ||lunarMonth > 12){
console.error("非法月======" + lunarMonth);
}
if(lunarDay < 1 ||lunarDay > 31){
console.error("非法天======" + lunarDay);
}
//计算该年闰几月
var leapMonth = getLeapMonth(lunarYear);
if (leapMonthFlag & leapMonth != lunarMonth) {
// console.error("非润月======");
}
}
2,计算该年闰几月
const getLeapMonth = year =>{
return (lunarInfo[year - 1900] & 0xf);
}
3,获取某闰年某月天数
const getMonthDays = (lunarYeay, month) =>{
if ((month > 31) || (month < 0)) {
throw (new Exception("月份有错!"));
}
// 0X0FFFF[0000 {1111 1111 1111} 1111]中间12位代表12个月,1为大月,0为小月
var bit = 1 << (16 - month);
if (((lunarInfo[lunarYeay - 1900] & 0x0FFFF) & bit) == 0) {
return 29;
} else {
return 30;
}
}
4,获取闰月天数
const getLeapMonthDays = year => {
if (getLeapMonth(year) != 0) {
if ((lunarInfo[year - 1900] & 0xf0000) == 0) {
return 29;
} else {
return 30;
}
} else {
return 0;
}
}
其他优化
1,计算公历日期是星期几,推算这个节假日放哪几天,比如说是星期三,那应该只放一天;如果是星期五或者星期一,那就正好连上周六日等等,这样的计算方法虽然不是很准,但基本可以猜个大概
2,清明节这个节日比较特殊,它不是按照农历也不是按照公历计算的,但基本是每年都是那几天中选一个;劳动节基本都是5.1到5.5,但2022年比较特殊,从4.30开始5天,综上还是以假日办公布的为准
边栏推荐
- Five kinds of 3D attention/transformer finishing (a-scn, point attention, CAA, offset attention, point transformer)
- Pytorch custom CUDA operator tutorial and runtime analysis
- Deep understanding of Kalman filter (3): multidimensional Kalman filter
- The fifth day of learning C language
- Huawei machine test question: Martian computing JS
- Deep understanding of Kalman filter (1): background knowledge
- 1640. 能否连接形成数组-c语言实现
- qt中使用sqlite同时打开多个数据库文件
- QT uses SQLite to open multiple database files at the same time
- async/await的执行顺序以及宏任务和微任务
猜你喜欢

Understand various IOU loss functions in target detection

被三星和台积电挤压的Intel终放下身段,为中国芯片定制芯片工艺
![Software testing function testing a full set of common interview questions [function testing - zero foundation] essential 4-1](/img/1c/c1c1b15e502ee901a396840c01e84d.png)
Software testing function testing a full set of common interview questions [function testing - zero foundation] essential 4-1

CUDA programming-04: CUDA memory model

PVT's spatial reduction attention (SRA)
![[acl2020] a novel method of component syntax tree serialization](/img/24/b8ec489966f7b1deef82b2eefa4d1b.png)
[acl2020] a novel method of component syntax tree serialization
![[C language - zero foundation lesson 6] input and output sentence format and compound sentence](/img/d5/b9935a37b634db7f5740779009e44f.png)
[C language - zero foundation lesson 6] input and output sentence format and compound sentence

ES6 new symbol data type

CUDA Programming -03: thread level

ctfshow 终极考核
随机推荐
Linux Installation and remote connection MySQL records
openharmony萌新贡献指南
Principle of flex:1
Two tips in arkui framework
软件测试功能测试全套常见面试题【功能测试-零基础】必备4-1
Day 8 of learning C language
NPM and yarn update dependent packages
Is the operation of assigning values to int variables atomic?
罗克韦尔AB PLC 通过RSLinx Classic与PLC建立通信的具体方法步骤
How to optimize the deep learning model to improve the reasoning speed
ES6 new - deconstruction assignment of array / object
1640. 能否连接形成数组-c语言实现
ES6 new - string part
The execution sequence of async/await, macro tasks and micro tasks
Nut joke based on arkui ETS
Cross domain and processing cross domain
Five kinds of 3D attention/transformer finishing (a-scn, point attention, CAA, offset attention, point transformer)
Replace restricts the text box to regular expressions of numbers, numbers, letters, etc
5g failed to stimulate the development of the industry, which disappointed not only operators, but also mobile phone enterprises
< script> detailed explanation of label content