【已解决】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
yq-ysy
论坛版主
帖子: 4660
注册时间: 2008-07-19 12:44
来自: 广西(桂)南宁(邕)

【已解决】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#1

帖子 yq-ysy » 2013-06-12 22:04

问题是从公历6月8日开始的,这一天应该是农历五月初一,但程序仍计算为四月三十。
某些民间推算的万年历也说公历6月8日是四月三十。但是因为今年2013年的农历四月是小月,所以只有29天。
多一天少一天,下一次“满月、月食、日食”的时间肯定就跟着错,因此谁对谁错,很明显,到时一眼能看出来。
官方公布的农历,相信是经过严格的天文学计算的,所以还是应该以官方的农历为准。

麻烦的是,这个“小月”的出现好像没有什么特定的规律,似乎是什么时候觉得误差大了,该小月就小月了,
所以写程序的话,处理起来就比较麻烦。
网上搜索了一下,不单是这个程序有错误,就连微软的outlook 2010版在这里也出错了。
这个用在conky上的农历程序不知道应该怎么修改,补回这一天?
谢谢

代码: 全选

#!/bin/bash
DOM=(0xd4a8 0xd4a0 0xda50 0x5aa8 0x56a0 0xaad8 0x25d0 0x92d0 0xc958 0xa950
    0xb4a0 0xb550 0xb550 0x55a8 0x4ba0 0xa5b0 0x52b8 0x52b0 0xa930 0x74a8
    0x6aa0 0xad50 0x4da8 0x4b60 0x9570 0xa4e0 0xd260 0xe930 0xd530 0x5aa0
    0x6b50 0x96d0 0x4ae8 0x4ad0 0xa4d0 0xd258 0xd250 0xd520 0xdaa0 0xb5a0
    0x56d0 0x4ad8 0x49b0 0xa4b8 0xa4b0 0xaa50 0xb528 0x6d20 0xada0 0x55b0)
LMOY=(0x40 0x02 0x07 0x00 0x50
     0x04 0x09 0x00 0x60 0x04
     0x00 0x20 0x60 0x05 0x00
     0x30 0xb0 0x06 0x00 0x50
     0x02 0x07 0x00 0x50 0x03)
START=2001; END=2050
# $1: 2001-2050
get_leap_month()
{
   sft=$(( $1 - $START )); dom=${LMOY[$(( $sft >> 1 ))]}
   echo $(( $(( sft & 1 ))?$(( $dom & 0x0f )):$(( $dom >> 4 )) ))
}
# $1: 2001-2050, $2: 1-12
get_days_of_month()
{
   y=$1; m=$2; high=0; low=29; sft=$(( 16 - $m ))
   dom=${DOM[$(( $y - $START ))]}; lmoy=$(get_leap_month $y)
   [ $m -gt $lmoy -a $lmoy -gt 0 ] && let "sft--"
   [ $(( $dom & $(( 1 << $sft )) )) -gt 0 ] && let "low++"
   if [ $m -eq $lmoy ]; then
      let "sft--"
      high=$(( $(( $dom & ( 1 << $sft ) ))?30:29 ))
   fi
   echo $(( low + ( high << 16) ))
}
# $1: 2001-2050
get_days_of_year()
{
   y=$1; d=0
   for i in {1..12}; do
      tmp=$(get_days_of_month $y $i)
      let "d+=$(( $(( $tmp >> 16)) & 0xffff ))"
      let "d+=$(( $tmp & 0xffff ))"
   done
   echo $d
}
#
parse_year()
{
   HS="甲乙丙丁戊己庚辛壬癸"; EB="子丑寅卯辰巳午未申酉戌亥"
   echo "${HS:$(( ($1 - 4) % 10 )):1}${EB:$(( ($1 - 4) % 12 )):1}"
}   
#
parse_month()
{
   LM=('' '正' '二' '三' '四' '五' '六' '七' '八' '九' '十' '十一' '十二')
   echo "${LM[$1]}"
}
#
parse_day()
{
   PREFIX="初十廿"; DAY="一二三四五六七八九十"
   d=$1
   if [ $d -eq 20 ]; then
      echo "二十"
   elif [ $d -eq 30 ]; then
      echo "三十"
   else
      echo "${PREFIX:$(( ($d - 1) / 10 )):1}${DAY:$(( ($d - 1) % 10 )):1}"
   fi
}
parse_date()
{
#   d=${*:-$(date)}; leap=
  d=${*:-$(date +"%Y/%m/%d")}; leap=
  sft=$(( ( $(date -d "$d" +%s) - $(date -d "${START}/01/01" +%s) ) / 60 / 60 / 24 ))
   if [ $sft -lt 23 ]; then
      ly=2000
      lm=12
      ld=$(( $sft + 7 ))
   else
      let "sft-=23"; ly=2001; lm=1; ld=1
      tmp=$(get_days_of_year $ly)
      while [ $sft -ge $tmp ]; do
         let "sft-=$tmp"
         let "ly++"
         tmp=$(get_days_of_year $ly)
      done
      tmp=$(( $(get_days_of_month $ly $lm) & 0xffff ))
      while [ $sft -ge $tmp ]; do
         let "sft-=$tmp"
         if [ $lm -eq $(get_leap_month $ly) ]; then
            tmp=$(( $(get_days_of_month $ly $lm) >> 16 ))
            if [ $sft -lt $tmp ]; then
               test $tmp -gt 0 && leap="闰"
               break
            fi
            let "sft-=$tmp"
         fi
         let "lm++"
         tmp=$(( $(get_days_of_month $ly $lm) & 0xffff ))
      done
      let "ld+=$sft"
   fi
   echo "$(parse_year $ly)年${leap}$(parse_month $lm)月$(parse_day $ld)"
}
parse_date "$*"
头像
qy117121
论坛版主
帖子: 50587
注册时间: 2007-12-14 13:40
系统: Winbuntu
来自: 志虚国乌由市
联系:

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#2

帖子 qy117121 » 2013-06-12 22:29

我感觉吧,这玩意还是从数据库里读取的好
比如像ee这样的 viewtopic.php?f=63&t=309740&start=231
渠月 · QY   
本人只会灌水,不负责回答问题
无聊可以点一下→ http://u.nu/ubuntu

邮箱 chuan@ubuntu.org.cn
头像
qy117121
论坛版主
帖子: 50587
注册时间: 2007-12-14 13:40
系统: Winbuntu
来自: 志虚国乌由市
联系:

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#3

帖子 qy117121 » 2013-06-12 22:42

去看了下万年历,貌似10年12年的四月也都是小月啊,特地把本地时间改为了10年6月12日(五月初一),没出错
渠月 · QY   
本人只会灌水,不负责回答问题
无聊可以点一下→ http://u.nu/ubuntu

邮箱 chuan@ubuntu.org.cn
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#4

帖子 eexpress » 2013-06-13 10:11

农历历来要手动调整的啊。准确的说,没算法的。
● 鸣学
头像
daf3707
论坛版主
帖子: 12739
注册时间: 2007-06-13 15:57
来自: 在他乡

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#5

帖子 daf3707 » 2013-06-13 10:14

http://www.nongli.com/item3/
这里的6.8是初一
手动也有规律吧,四舍五入? :em05
头像
和羞走
帖子: 249
注册时间: 2012-07-09 11:00

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#6

帖子 和羞走 » 2013-06-13 10:19

eexpress 写了:农历历来要手动调整的啊。准确的说,没算法的。
蹴罢秋千,起来慵整纤纤手。露浓花瘦,薄汗轻衣透。
见有人来,袜划金钩溜,和羞走。倚门回首,却把青梅嗅。
头像
yq-ysy
论坛版主
帖子: 4660
注册时间: 2008-07-19 12:44
来自: 广西(桂)南宁(邕)

Re: 【求助】今年的6月8日恰逢农历4月是小月,只有29天,造成农历程序错误少了一天,怎么补回来?

#7

帖子 yq-ysy » 2013-06-16 21:21

手动调整农历程序,修正误差:
修改这一行 sft=$(( ( $(date -d "$d" +%s) - $(date -d "${START}/01/01" +%s) ) / 60 / 60 / 24 ))
在最后的双括号之内加上(或者减去)误差的天数即可:
修改后 sft=$(( ( $(date -d "$d" +%s) - $(date -d "${START}/01/01" +%s) ) / 60 / 60 / 24 +1 ))
回复