好些天没有登陆邮箱,前几天上班打开一看垃圾箱中有一封邮件让我好激动,还是国外友人的英文邮件。^_^
大概内容是我早些时候写的一个阳历转农历的shell小程序,他在用的时候发现了bug,但是这个bug我在去年年底就修改了。而且,他给了此程序的具体出处,但并不是我发布此程序的地址,显然是XX拷贝过去的(管它XX是人还是机器),庆幸的是我在程序的log文件中加入了我的邮箱地址,此友人才能找到我。废话少说,入正题。

缘由

本脚本实现原理是查表法(因为公式有误差);基于农历新年为基准,对农历新年前后两个不同的农历进行计算。

写这个脚本之前是想在Linux 终端命令提示符中加入阳历及农历日期。在Ubuntu中有Lunar软件可以获取农历日期,但在Fedora或CentOS中并没有类似软件,所以就想自己来实现一个,但网上用其他语言写的一大把,如果再写没什么必要。所以就想用shell来写一个。

主要功能

将阳历转换为农历。

Ubuntu 12.04 LTS dash和bash都测试通过(在此系统中,默认的/bin/sh是连接到/bin/dash的,dash是一个小而相容于POSIX标准的Unix shell,bash进行了扩展)

CentOS 6.4 测试通过(很久以前的事了,限于手中的资源,现在就不再在此系统上测试,不知道现在的版本还能否通过)

Fedora 18 测试通过(很久以前的事了,限于手中的资源,现在就不再在此系统上测试,不知道现在的版本还能否通过)

参数要求

  • 参数数据为8位,其中年为4位,月和日各2位,不足前面补0,如2013年1月1号:20130101
  • 无参数时默认当前系统日期为需转换日期

农历是通过观测及推算而得出的历法,所以通过通用公式计算得到的农历时间多少会有误差,特别是时间范围比较大的时候,这种误差就不好再无视它了。

基本算法:以每年的农历新年为基准。新年后的农历年份对应于阳历所在的年份;新年前为上一个农历年份。

验证

如果想验证可通过以下网址进行验证:

http://www.herongyang.com/Year_zh/Program-Chinese-Calendar-Algorithm.html

数据来源

以下关键的农历元数据来源于:

http://www.cppblog.com/ctou45/archive/2012/08/21/187846.html

//0~4 共5bit 春节日

//5~6 共2bit 春节月

//7~19 共13bit 13个月的大小月情况(如果无闰月,最后位无效),大月为1,小月为0(从左到右)

//20~23 共4bit 记录闰月的月份,如果没有闰月为0

0x04AE53,0x0A5748,0x5526BD,0x0D2650,0x0D9544,
0x46AAB9,0x056A4D,0x09AD42,0x24AEB6,0x04AE4A, //1901-1910 0x6A4DBE,0x0A4D52,0x0D2546,0x5D52BA,0x0B544E,
0x0D6A43,0x296D37,0x095B4B,0x749BC1,0x049754, //1911-1920 0x0A4B48,0x5B25BC,0x06A550,0x06D445,0x4ADAB8,
0x02B64D,0x095742,0x2497B7,0x04974A,0x664B3E, //1921-1930 0x0D4A51,0x0EA546,0x56D4BA,0x05AD4E,0x02B644,
0x393738,0x092E4B,0x7C96BF,0x0C9553,0x0D4A48, //1931-1940 0x6DA53B,0x0B554F,0x056A45,0x4AADB9,0x025D4D,
0x092D42,0x2C95B6,0x0A954A,0x7B4ABD,0x06CA51, //1941-1950 0x0B5546,0x555ABB,0x04DA4E,0x0A5B43,0x352BB8,
0x052B4C,0x8A953F,0x0E9552,0x06AA48,0x7AD53C, //1951-1960 0x0AB54F,0x04B645,0x4A5739,0x0A574D,0x052642,
0x3E9335,0x0D9549,0x75AABE,0x056A51,0x096D46, //1961-1970 0x54AEBB,0x04AD4F,0x0A4D43,0x4D26B7,0x0D254B,
0x8D52BF,0x0B5452,0x0B6A47,0x696D3C,0x095B50, //1971-1980 0x049B45,0x4A4BB9,0x0A4B4D,0xAB25C2,0x06A554,
0x06D449,0x6ADA3D,0x0AB651,0x093746,0x5497BB, //1981-1990 0x04974F,0x064B44,0x36A537,0x0EA54A,0x86B2BF,
0x05AC53,0x0AB647,0x5936BC,0x092E50,0x0C9645, //1991-2000 0x4D4AB8,0x0D4A4C,0x0DA541,0x25AAB6,0x056A49,
0x7AADBD,0x025D52,0x092D47,0x5C95BA,0x0A954E, //2001-2010 0x0B4A43,0x4B5537,0x0AD54A,0x955ABF,0x04BA53,
0x0A5B48,0x652BBC,0x052B50,0x0A9345,0x474AB9, //2011-2020 0x06AA4C,0x0AD541,0x24DAB6,0x04B64A,0x69573D,
0x0A4E51,0x0D2646,0x5E933A,0x0D534D,0x05AA43, //2021-2030 0x36B537,0x096D4B,0xB4AEBF,0x04AD53,0x0A4D48,
0x6D25BC,0x0D254F,0x0D5244,0x5DAA38,0x0B5A4C, //2031-2040 0x056D41,0x24ADB6,0x049B4A,0x7A4BBE,0x0A4B51,
0x0AA546,0x5B52BA,0x06D24E,0x0ADA42,0x355B37, //2041-2050 0x09374B,0x8497C1,0x049753,0x064B48,0x66A53C,
0x0EA54F,0x06B244,0x4AB638,0x0AAE4C,0x092E42, //2051-2060 0x3C9735,0x0C9649,0x7D4ABD,0x0D4A51,0x0DA545,
0x55AABA,0x056A4E,0x0A6D43,0x452EB7,0x052D4B, //2061-2070 0x8A95BF,0x0A9553,0x0B4A47,0x6B553B,0x0AD54F,
0x055A45,0x4A5D38,0x0A5B4C,0x052B42,0x3A93B6, //2071-2080 0x069349,0x7729BD,0x06AA51,0x0AD546,0x54DABA,
0x04B64E,0x0A5743,0x452738,0x0D264A,0x8E933E, //2081-2090 0x0D5252,0x0DAA47,0x66B53B,0x056D4F,0x04AE45,
0x4A4EB9,0x0A4D4C,0x0D1541,0x2D92B5 //2091-2099

主要代码

因为时常更新,所以打包文件不再提供,只提供github。

github地址:

https://github.com/snowsolf/lunar

此程序包括如下几个文件:

  • lunar.sh 主脚本,具体实现
  • datebases 农历元数据
  • change.log 更改日志
  • readme 脚本说明及注意事项
  • shengxiao 生肖数据

主脚本

lunar.sh代码如下:

#########################################################################
# File Name: lunar.sh
# Author: snowsolf
# E-mail: snowsolf@hotmail.com
# Created Time: 2013年07月***********
#########################################################################
#!/bin/sh Version=1.0
Editor=snowsolf
Email=snowsolf@hotmail.com # print help
function Usage()
{
cat << EOF
==============================================================
Valid date: ~
But 'date' program support: ~ -h, --help display this help and exit
-V, --version output version information and exit Usage: $ [-h|--help|-V|--version] | [date(yyyymmdd)] Examples:
Usage input time: $
Usage system time: $ Editor: $Editor
E-mail: $Email
EOF
exit
} #################################################################
#get year,month,day and day of year
#system 'date' program support: ~
#################################################################
function Date_data()
{
date_year=$(echo $DATE |sed 's/^\(.\{4\}\).*/\1/')
date_month=$(echo $DATE |sed 's/.*\(..\)..$/\1/')
date_day=$(echo $DATE |sed 's/.*\(..\)$/\1/')
date_days=$(date -d $DATE +%j)
} DATE=$@
# handle difference input
case "$#" in
)
echo "No parameters!"
echo -e "Usage system time: $(date +%Y-%m-%d)\n"
DATE=$(date +%Y%m%d)
Date_data
;;
)
date -d $DATE +%j > /dev/null || ((Usage && exit ))
case "$1" in
-h|--help)
Usage
;;
-V|--version)
echo "$0: Version $Version"
echo "Editor: $Editor"
echo "E-mail: $Email"
exit
;;
[][][-][-][-][-][-][-]|[][][-][-][-][-][-][-])
[ "$1" -ge "" ] && [ "$1" -lt "" ] || [ "$1" -gt "" ] && [ "$1" -le "" ] \
&& echo -e "'date' program no support: $1\n" && Usage
[ "$1" -ge "" ] && [ "$1" -lt "" ] || [ "$1" -gt "" ] && [ "$1" -le "" ] \
&& echo -e "Invalid parameter: $1\n" && Usage
Date_data
;;
*)
echo -e "Invalid parameter: $1\n"
Usage
;;
esac
;;
*)
echo -e "The number of parameter greater than one !\n"
Usage
;;
esac # lunar databases
databases_path=databases # get lunar year
lunar_year=$(sed /$date_year/!d $databases_path |sed 's/^\(....\).*/\1/') # get all for lunar year, and form hexadecimal to binary
# include lunar year, month, day, and leap month
lunar_year_data=$(sed /$date_year/!d $databases_path |sed 's/.*\ \(.*\)/\1/')
lunar_year_data_bin=$(echo "ibase=16;obase=2;$lunar_year_data"|bc |sed -e :a -e 's/^.\{1,23\}$/0&/;ta') new_year_month_bin=$(echo $lunar_year_data_bin |sed -e 's/^.\{17\}\(.\{2\}\).*/\1/')
new_year_month=$(echo "ibase=2;$new_year_month_bin"|bc |sed -e :a -e 's/^.\{1,1\}$/0&/;ta') new_year_day_bin=$(echo $lunar_year_data_bin |sed -e 's/.*\(.\{5\}\)$/\1/')
new_year_day=$(echo "ibase=2;$new_year_day_bin"|bc |sed -e :a -e 's/^.\{1,1\}$/0&/;ta') new_year_days=$(date -d $date_year$new_year_month$new_year_day +%j)
lunar_days=$(expr $date_days - $new_year_days + )
# flag
befor_or_after= if [ "$lunar_days" -le "" ]; then
befor_or_after=
date_year=$(($date_year - )) lunar_year=$(sed /$date_year/!d $databases_path |sed 's/^\(....\).*/\1/') lunar_year_data=$(sed /$date_year/!d $databases_path |sed 's/.*\ \(.*\)/\1/')
lunar_year_data_bin=$(echo "ibase=16;obase=2;$lunar_year_data"|bc |sed -e :a -e 's/^.\{1,23\}$/0&/;ta')
fi lunar_leap_month_bin=$(echo $lunar_year_data_bin |sed -e 's/^\(.\{4\}\).*/\1/')
lunar_leap_month=$(echo "ibase=2;$lunar_leap_month_bin"|bc) lunar_month_all_bin=$(echo $lunar_year_data_bin |sed -e 's/^.\{4\}\(.\{13\}\).*/\1/')
[ "$lunar_leap_month" = "" ] && lunar_month_all_bin=$(echo $lunar_year_data_bin |sed -e 's/^.\{4\}\(.\{12\}\).*/\1/')
lunar_month_all=$(echo $lunar_month_all_bin |sed -e 's/0/29\ /g' |sed -e 's/1/30\ /g') if [ "$befor_or_after" = "" ];then
lunar_month=
lunar_day=$lunar_days
for i in $lunar_month_all
do
[ "$lunar_day" -eq "$i" ] && break
[ "$lunar_day" -gt "$i" ] && lunar_day=$(($lunar_day - $i)) && lunar_month=$(($lunar_month + ))
done
else
lunar_month=
lunar_day=$((-$lunar_days))
lunar_month_all_bin=$(echo $lunar_month_all_bin |rev)
lunar_month_all=$(echo $lunar_month_all_bin |sed -e 's/0/29\ /g' |sed -e 's/1/30\ /g')
for i in $lunar_month_all
do
[ "$lunar_day" -eq "$i" ] && break
if [ "$lunar_day" -gt "$i" ]; then
lunar_day=$(($lunar_day - $i))
lunar_month=$(($lunar_month - ))
else
lunar_day=$(($i - $lunar_day))
break
fi
done
fi # output
if [ "$lunar_leap_month" = "" ]; then
echo $lunar_year-$lunar_month-$lunar_day
else
if [ "$lunar_leap_month" -ge "$lunar_month" ]; then
echo $lunar_year-$lunar_month-$lunar_day
elif [ "$befor_or_after" = "" ]; then
if [ "$(($lunar_leap_month + 1))" = "$lunar_month" ];then
lunar_month=$(($lunar_month - ))
echo $lunar_year-*$lunar_month-$lunar_day
else
lunar_month=$(($lunar_month - ))
echo $lunar_year-$lunar_month-$lunar_day
fi
else
echo $lunar_year-$lunar_month-$lunar_day
fi
fi sed -n $(($(($lunar_year - + )) % ))p shengxiao

lunar.sh

数据文件

databases文件中存储了日期的元数据。为了更容易查表,此文件对元数据进行了处理。

  04AE53
0A5748
5526BD
0D2650
0D9544
46AAB9
056A4D
09AD42
24AEB6
04AE4A
6A4DBE
0A4D52
0D2546
5D52BA
0B544E
0D6A43
296D37
095B4B
749BC1 0A4B48
5B25BC
06A550
06D445
4ADAB8
02B64D 2497B7
04974A
664B3E
0D4A51
0EA546
56D4BA
05AD4E
02B644 092E4B
7C96BF
0C9553
0D4A48
6DA53B
0B554F
056A45
4AADB9
025D4D
092D42
2C95B6
0A954A
7B4ABD
06CA51
0B5546
555ABB
04DA4E
0A5B43
352BB8
052B4C
8A953F
0E9552
06AA48
7AD53C
0AB54F
04B645
4A5739
0A574D 3E9335
0D9549
75AABE
056A51
096D46
54AEBB
04AD4F
0A4D43
4D26B7
0D254B
8D52BF
0B5452
0B6A47
696D3C
095B50
049B45
4A4BB9
0A4B4D
AB25C2
06A554
06D449
6ADA3D
0AB651 5497BB
04974F
064B44
36A537
0EA54A
86B2BF
05AC53
0AB647
5936BC
092E50
0C9645
4D4AB8
0D4A4C
0DA541
25AAB6
056A49
7AADBD
025D52
092D47
5C95BA
0A954E
0B4A43
4B5537
0AD54A
955ABF
04BA53
0A5B48
652BBC
052B50
0A9345
474AB9
06AA4C
0AD541
24DAB6
04B64A
69573D
0A4E51
0D2646
5E933A
0D534D
05AA43
36B537
096D4B
B4AEBF
04AD53
0A4D48
6D25BC
0D254F
0D5244
5DAA38
0B5A4C
056D41
24ADB6
049B4A
7A4BBE
0A4B51
0AA546
5B52BA
06D24E
0ADA42
355B37
09374B
8497C1 064B48
66A53C
0EA54F
06B244
4AB638
0AAE4C
092E42
3C9735
0C9649
7D4ABD
0D4A51
0DA545
55AABA
056A4E
0A6D43
452EB7
052D4B
8A95BF
0A9553
0B4A47
6B553B
0AD54F
055A45
4A5D38
0A5B4C
052B42
3A93B6 7729BD
06AA51
0AD546
54DABA
04B64E
0A5743 0D264A
8E933E
0D5252
0DAA47
66B53B
056D4F
04AE45
4A4EB9
0A4D4C
0D1541
2D92B5

databases

生肖数据

shengxiao文件中是生肖:












shengxiao

下个功能点

下个功能点是阳历日期的实现,因为系统中date程序支持的时间范围是1901-12-15到2038-01-19,显然有时此时间段并不能满足一些人的要求。所以,下一步需要单独实现如date程序功能的代码,以支持更大的时间段。

但你可知道1752年的9月是有问题的,具体缘由你可以google(话说这些天已经不好使了,我只能说,是不是被玩坏了!)或者baidu。

下个shell程序

Ubuntu 14.04 LTS出来的时候,我就迫不及待的将12.04 LTS升级到14.04 LTS,但是除了问题TMD还是问题:

*开机情况下合起笔记本盖子再打开时X僵死了,好烦躁!
*蓝牙适配器不能用了!
*每次打开电脑都会有系统错误提示,还不止一个!

所以,前天晚上将必要的数据备份后还是装回12.04,感觉整个人都舒服了。

之前UbuntuKylin出来的时候就下了天气插件使用,但不管12.04还是14.04上都会莫名其妙的死掉,所以就萌生了用shell实现一个天气察看程序,但不知道天气元数据怎么获取(中国气象局的数据),之前看了UbuntuKylin的天气插件源码,但没找到。

最后

农历是通过观测及推算而得出的历法,一直没有找到元数据的出处,这个应该天文台有,但网上找不到。

还有天气数据是从那里获取?

还望知道的大哥大姐小弟小妹告诉我。不胜感激!

更新

2014-08-01

将此脚本托管到github上,并将readme内容更新到README.md文件中。

Linux-shell实现阳历转农历(序)的更多相关文章

  1. Linux shell实现阳历转农历

    闲来无事,想在Linux下用shell写一个阳历转农历的脚本,断断续续大概一个星期终于搞定.现在拿出来与大家分享. 缘由 本脚本实现原理是查表法(因为公式有误差):基于农历新年为基准,对农历新年前后两 ...

  2. Linux Shell 文本处理工具集锦 zz

    内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq 消除重复行 用tr进行转换 cut 按列切分文本 paste 按列拼接文本 wc 统计行和字符 ...

  3. Linux Shell 文本处理工具集锦

    本文将介绍Linux下使用Shell处理文本时最常用的工具:find.grep.xargs.sort.uniq.tr.cut.paste.wc.sed.awk:提供的例子和参数都是最常用和最为实用的: ...

  4. [转] Linux Shell 文本处理工具集锦

    内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq 消除重复行 用tr进行转换 cut 按列切分文本 paste 按列拼接文本 wc 统计行和字符 ...

  5. 老李分享:《Linux Shell脚本攻略》 要点(四)

    老李分享:<Linux Shell脚本攻略> 要点(四)   1.IP地址的正则表达式: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 2. ...

  6. 老李分享:《Linux Shell脚本攻略》 要点(二)

    老李分享:<Linux Shell脚本攻略> 要点(二)   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课 ...

  7. Linux Shell基础(下)

    Linux Shell基础(下) 目录 一.shell特殊符号cut命令 二.cut.sort.wc.uniq命令 三.tee.tr.split命令 四.简易审计系统 五.fork, exec, so ...

  8. linux shell 编程参考

    #!/bin/bash my_fun() { echo "$#" } echo 'the number of parameter in "$@" is '$(m ...

  9. Linux Shell 裡一些很少用到卻很有用的指令

    Linux Shell 裡一些很少用到卻很有用的指令 2009年11月30日 13:53:00 yaoyasong 阅读数:414   Linux Shell 裡一些很少用到卻很有用的指令 你是不是已 ...

随机推荐

  1. nyoj-1092-数字分隔(二)

    java大法好啊 思路:单独拿出整数部分分隔 题目链接 import java.math.BigDecimal; import java.util.Scanner; public class Main ...

  2. cocos2dx混合模式应用———制作新手引导高亮区域 (2.2.0)

    cocos2dx混合模式应用———制作新手引导高亮区域 转自:http://www.cnblogs.com/mrblue/p/3455775.html 首先,效果预览一下 高亮区域的图片: 示例代码: ...

  3. HihoCoder1403 后缀数组一·重复旋律1

    后缀数组一·重复旋律 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列. 小Hi ...

  4. BZOJ5334: [Tjoi2018]数学计算

    BZOJ5334: [Tjoi2018]数学计算 https://lydsy.com/JudgeOnline/problem.php?id=5334 分析: 线段树按时间分治即可. 代码: #incl ...

  5. Python collections系列之计数器

    计数器(counter) Counter是对字典(无序)类型的补充,用于追踪值的出现次数. 使用counter需要导入 collections 类 ps:具备字典的所有功能 + 自己的功能 1.创建一 ...

  6. zabbix监控进程

    参考http://chenx1242.blog.51cto.com/10430133/1837990 1 前期说明 zabbix_server查看“文件在后台运行数量”所对应的key就是:proc.n ...

  7. JDBC小常识

    1 JDBC连接数据库6步 Load the JDBC Driver Establish the Database Connection Create a Statement Object Execu ...

  8. 用Json Template在Azure上创建Cisco CSR路由器

    Azure的ARM模式可以通过Json的模板创建VM.本文以Cisco的CSR的image为例,介绍如何用Json的创建VM. 一.Cisco CSR的Image 首先把Cisco CSR的image ...

  9. IE版本的标准定义

    解决方案 首页加代码把IE浏览器的标准改了,无论客户用的什么IE,都是按照IE7的标准来的. <meta http-equiv="X-UA-Compatible" conte ...

  10. hihoCoder#1068(RMQ-ST算法)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在美国旅行了相当长的一段时间之后,终于准备要回国啦!而在回国之前,他们准备去超市采购一些当地特产——比如汉堡 ...