Linux-shell实现阳历转农历(序)
好些天没有登陆邮箱,前几天上班打开一看垃圾箱中有一封邮件让我好激动,还是国外友人的英文邮件。^_^
大概内容是我早些时候写的一个阳历转农历的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实现阳历转农历(序)的更多相关文章
- Linux shell实现阳历转农历
闲来无事,想在Linux下用shell写一个阳历转农历的脚本,断断续续大概一个星期终于搞定.现在拿出来与大家分享. 缘由 本脚本实现原理是查表法(因为公式有误差):基于农历新年为基准,对农历新年前后两 ...
- Linux Shell 文本处理工具集锦 zz
内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq 消除重复行 用tr进行转换 cut 按列切分文本 paste 按列拼接文本 wc 统计行和字符 ...
- Linux Shell 文本处理工具集锦
本文将介绍Linux下使用Shell处理文本时最常用的工具:find.grep.xargs.sort.uniq.tr.cut.paste.wc.sed.awk:提供的例子和参数都是最常用和最为实用的: ...
- [转] Linux Shell 文本处理工具集锦
内容目录: find 文件查找 grep 文本搜索 xargs 命令行参数转换 sort 排序 uniq 消除重复行 用tr进行转换 cut 按列切分文本 paste 按列拼接文本 wc 统计行和字符 ...
- 老李分享:《Linux Shell脚本攻略》 要点(四)
老李分享:<Linux Shell脚本攻略> 要点(四) 1.IP地址的正则表达式: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 2. ...
- 老李分享:《Linux Shell脚本攻略》 要点(二)
老李分享:<Linux Shell脚本攻略> 要点(二) poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课 ...
- Linux Shell基础(下)
Linux Shell基础(下) 目录 一.shell特殊符号cut命令 二.cut.sort.wc.uniq命令 三.tee.tr.split命令 四.简易审计系统 五.fork, exec, so ...
- linux shell 编程参考
#!/bin/bash my_fun() { echo "$#" } echo 'the number of parameter in "$@" is '$(m ...
- Linux Shell 裡一些很少用到卻很有用的指令
Linux Shell 裡一些很少用到卻很有用的指令 2009年11月30日 13:53:00 yaoyasong 阅读数:414 Linux Shell 裡一些很少用到卻很有用的指令 你是不是已 ...
随机推荐
- 关于stl advance函数移动步数超过容器大小(越界)的研究
今天使用advance遇到个问题,当advance移动步数超过容器大小时,表现的结果居然不一样. 再来看下stl源码 template<typename _BidirectionalIterat ...
- java 网页 保存上传文件
网页请求提交到另外一个jsp 进行处理 index.jsp <%@ page language="java" import="java.util.*" p ...
- UVA - 11754 Code Feat (分块+中国剩余定理)
对于一个正整数N,给出C组限制条件,每组限制条件为N%X[i]∈{Y1,Y2,Y3,...,Yk[i]},求满足条件的前S小的N. 这道题很容易想到用中国剩余定理,然后用求第k小集合的方法输出答案.但 ...
- python_广州房价热力图
调用百度地图api,获取经纬度数据,然后在调用百度地图api,生成热力图 import pandas as pd import numpy as np data = pd.read_excel(r'D ...
- xftp连接不上阿里云服务器
打开xftp默认是使用FTP协议,要连接到云服务器,需要将协议改为SFTP 连接成功
- Azure的CentOS上安装LIS (Linux Integration Service)
Azure上虚拟化技术都是采用的Hyper-v,每台Linux虚拟机都安装了LIS(Linux Integration Service).LIS的功能是为VM提供各种虚拟设备的驱动.所以LIS直接影响 ...
- laravel 配置文件的使用
在开发的时候有许多数据是固定的 或者是多处使用的, 那么我们可以把它保存到配置文件中, 这样将来我们可以直接从配置文件中读取这个数据,如果有特殊的数据需要改变的时候,我们也可以在单独特定的环境中,不使 ...
- iperf 网络测速
1.介绍 1) # ipref -g //这个最直观 2)Iperf 是一个网络性能测试工具.Iperf可以测试最大TCP和UDP带宽性能.Iperf具有多种参数和UDP特性,可以根据需要调整. ...
- 几种排序方式的java实现(02:希尔排序,归并排序,堆排序)
代码(部分为别人代码): 1.希尔排序(ShellSort) /* * 希尔排序:先取一个小于n的整数d1作为第一个增量, * 把文件的全部记录分成(n除以d1)个组.所有距离为d1的倍数的记录放在同 ...
- Java-API:java.util.Random
ylbtech-Java-API:java.util.Random 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 1. https://docs.oracle. ...