There is nothing to do, want to use the shell in Linux to write a Gregorian calendar to the lunar script, intermittent about one weeks finally finished. Now take it out and share it with you.
1. Why
This script implementation principle is look-up table method (because the formula has error), based on the Lunar New Year, the Lunar New year before and after two different lunar calendar calculation.
Before writing this script, you want to add the Gregorian and lunar dates to the Linux terminal command prompt. There are lunar software in Ubuntu to get the lunar date, but there is no similar software in Fedora or CentOS, so you want to do it yourself, but a lot of it is written in other languages, and it's not necessary to write it again. So I want to use the shell to write one.
2, function and use
Function: Converts specific Gregorian dates to lunar dates.
Time range: 1901~2099, corresponding to the lunar year time for 4598~4796
Parameter format (no parameter defaults to current system date): YYYYMMDD
As of January 1, 2013:
Copy Code code as follows:
$./lunar.sh 20130101
4709-11-20
3. Complete data
Full data download Link:
http://xiazai.jb51.net/201408/tools/lunar-20131202.7z
File in Package:
Lunar.sh The main script, specifically implement
datebases Lunar meta data
Change.log Change Log
Readme Script Description and Precautions
The main script lunar.sh code is as follows:
#!/bin/sh
DATE=$@
[ "$DATE" = "" ] && DATE=$(date +%Y%m%d)
databases_path=databases
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)
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')
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 + 1)
befor_or_after=0
if [ "$lunar_days" -le "0" ]; then
befor_or_after=1
date_year=$(($date_year - 1))
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" = "0" ] && 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" = "0" ];then
lunar_month=1
lunar_day=$lunar_days
for i in $lunar_month_all
do
[ "$lunar_day" -gt "$i" ] && lunar_day=$(($lunar_day - $i)) && lunar_month=$(($lunar_month + 1))
[ "$lunar_day" = "$i" ] && break
done
else
lunar_month=12
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
if [ "$lunar_day" -gt "$i" ]; then
lunar_day=$(($lunar_day - $i))
lunar_month=$(($lunar_month - 1))
else
lunar_day=$(($i - $lunar_day))
break
fi
done
fi
if [ "$lunar_leap_month" = "0" ]; 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" = "0" ]; then
if [ "$(($lunar_leap_month + 1))" = "$lunar_month" ];then
lunar_month=$(($lunar_month - 1))
echo $lunar_year-*$lunar_month-$lunar_day
else
lunar_month=$(($lunar_month - 1))
echo $lunar_year-$lunar_month-$lunar_day
fi
else
echo $lunar_year-$lunar_month-$lunar_day
fi
fi
lunar.sh
4 Revision History
2013-12-02
Bug found: If the lunar calendar was semi-rotary last month, this month, the last month's 30 output was the first day of the month, because 30 days last month, which is just 30 last month, and this month is 29 days, 29<30, the next cycle of the month to reduce the number of days, so that last month's 30 for this month's first
Bug modification: Add a Judgment statement, if the remainder of the lunar calendar is equal to the number of days of the month will not cycle