在小程序倒数记日发布之后,收到很多用户的反馈,对于国人来说,很多人的生日是用传统农历来计算的,因此添加农历很有必要,但是小程序的选择框组件没有提供内建的农历支持,就只能靠自己来实现了。首先我们要先了解农历有哪些特点:

我国现行的农历是阴阳历,即以夏历(阳历)为主辅助阴历而成的,农历本身无法通过计算机获得所需要的日期,其闰年,闰月,每个月的天数都是没有明显规律的。

目前通常的处理办法是查表法,将1900~2100年的年份的特征值写死直接取用,这里推荐使用 JS文件下载

这个库能够获取基本的农历信息,也基本上是我们所需要的,现在我们开始着手做一个选择器,这里我们会使用到微信组件库里的 picker-view 来实现:

  <view class='lunarPicker'>
    <picker-view bindchange="bindChange"  value="{{[year,month,day]}}">
      <picker-view-column>
        <view wx:for="{{lyears}}" wx:key="item" >{{item}}年</view>
      </picker-view-column>
      <picker-view-column>
        <view wx:for="{{months}}" wx:key="item" >{{item}}</view>
      </picker-view-column>
      <picker-view-column>
        <view wx:for="{{days}}" wx:key="item" >{{item}}</view>
      </picker-view-column>
    </picker-view>
  </view>

lyears 是所有的年份列表, months 是选中的年份的月份列表, days 是选中的月份的天数列表

首先先获取 lyears

function lyearList() {
    var list = [];
    for (var i = 1900; i <= 2100; i++) {
      list.push(i + calendar.toGanZhiYear(i))
    return list

根据年份获取 months

function lmonthList(y) {
    var monthList = [];
    for (var i = 1; i <= 12; i++) {
      monthList.push(calendar.toChinaMonth(i))
    let leapMonth = calendar.leapMonth(y);
    if (leapMonth) {
      monthList.splice(leapMonth, 0, "闰" + calendar.toChinaMonth(leapMonth))
    return monthList

根据月份和年份,以及月份是否为闰月来计算当前月的天数,可以得到 days

function ldaysList(y, m, isLeap) {
    var dayList = [];
    let dayCount = isLeap ? calendar.leapDays(y) : calendar.monthDays(y, m)
    for (var i = 1; i <= dayCount; i++) {
      dayList.push(calendar.toChinaDay(i))
    return dayList

*以上三个方法可以添加到 calendar.js

初始化进入选择器的时候,我们可以默认选择日期为初始化的日期,即传入 picker-view 的value:

onLoad: function (option) {
    let initDate = new Date()
    let initLunarDate = calendar.solar2lunar(initDate.getFullYear(), initDate.getMonth() + 1, initDate.getDate())
    this.setData({
      initLunarDate: initLunarDate,
    this.setData({
      month: calendar.getRightMonthIndex(originLunarDate.lYear, originLunarDate.lMonth, originLunarDate.isLeap) - 1,
      day: initLunarDate.lDay - 1,
      year: initLunarDate.lYear - 1900,

求月份的时候需要考虑到当前年是否有闰月,solar2lunar返回的是当月的月份值,(闰八月返回的是8,实际上这个是第九个月,接下来的九月实际上是第十个月)因此需要获得正确的index:

function getRightMonthIndex(y, m, isLeap) {
    let leapMonth = calendar.leapMonth(y);
    if (leapMonth) {
      if (!(m < leapMonth || (m == leapMonth && !isLeap))) {
        return m + 1