
Ubuntu日本語フォーラム

ログインしていません。
Ubuntu愛好者の皆様はじめまして。
バージョン14の頃からUbuntuを使っている者です。
現在は16.04 LTS 64ビット版を業務に使っています。
先月下旬より私が代表社員を務める会社の業務及び宣伝のために
業種、個人、法人の区別なく有用であると考えるフリーウェアを公開しています。
ソフトの内容は入力した日付のX日後またはX日前の日付の表示です。
どうぞご利用ください。
ダウンロードページ http://www.satoricorpo.com/sw.html
オフライン
以下は、#1で公開されたプログラムにちゃちゃを入れるつもりではないし、ましてや妨害するつもりでもないので、その点をご理解ください。
公開されたプログラムを拝見してて、GUIのほうはちと手間がかかりますが、CUIの方ならインタラクティブにしない限りbashのスクリプトで同等のものがなんとかなりそうなので作ってみました。
といっても、calコマンドと、dateコマンドを使っただけなんですが……
最初は差分計算を自前でやろうとしたんですが、年と月まではよくても、日の計算のところで閏年の扱いが"1500日後"とかめんどくさくなってしまいました。
ところが現在のdateコマンド(GNU製のdate)には、--date=STRING形式で指定した時に、STRINGの"2019/4/6 200 days ago"とかをちゃんと解釈してくれて"2019/4/6の200日前"の日付を出力してくれる素敵な機能があります。
しかも、年の差分、月の差分、日の差分を別々に、且つ、〜〜前(ago)と、〜〜後の混在指定が可能です。
この機能、"man date"にはあまりはっきりとは書かれておらず、次のような表現に留まっています。
"The --date=STRING is a mostly free format human readable date string such as "Sun, 29 Feb 2004 16:21:42 -0800" or "2004-02-29 16:21:42" or even "next Thursday". A date string may contain items indicating calendar date, time of day, time zone, day of week, relative time, relative date, and numbers. "
(--date=STRINGは、ほとんど自由形式の人間が読める日付文字列であり、"Sun、29 Feb 2004 16:21:42 -0800" や "2004-02-29 16:21:42" や "次の木曜日" でさえ指定出来ます。日付文字列には、カレンダーの日付、时刻、タイムゾーン、曜日、相対的な時間、相対的な日付、そして数字を示す項目を含むことができます。)
この辺の勉強も含めて作ってみました。
ほとんどネタかオモチャのようなものであって、動作確認も当方が使っているubuntu Desktop 16.04 LTSでしか行っていません。
その点ご理解のほどよろしくお願いいたします。
実際に動かしてみて「これバグか?」とか、スクリプトなので「なんでこんな書き方してるんだ?」とかのツッコミは歓迎致しますが、お手柔らかに。
以下はソースコードです。ダウンロードされる場合はこちら calcData.sh から。
#!/bin/bash
set -u
C_SCRIPT_NAME=`basename $0`
C_SCRIPT_FULL_PATH=`realpath $0`
C_SCRIPT_PATH=`dirname ${C_SCRIPT_FULL_PATH}`
#---------------------------------------------------------------------
#--- functions
#---------------------------------------------------------------------
function printUsage() {
local scriptName=$1
cat << USG
${scriptName}の使い方は……
${scriptName} [ -T 起点とする<日付> ]
[ -Y "年"の<差分値> ] [ -M "月"の<差分値> ] [ -D "日"の<差分値> ]
[ -h ]
<日付> := YYYYMMDD
<差分値> := [+|-] 数値
例1: ${scriptName} -Y 2 -D 10 (本日から)2年と10日後の日付を求める
例2: ${scriptName} -Y -2 -D +10 (本日から)2年前の日付から、更に10日後の日付を求める
例3: ${scriptName} -T 21120903 -Y -100 -D +10 2112/9/3("ドラえもん"の製造日)から100年前の日付から、更に10日後の日付を求める
例4: ${scriptName} -h 使い方(=現在表示してる内容)を表示する
特記事項 -Tのパラメータ指定の無い場合は、当日を起点とする日付として扱う
USG
return 0
}
function isDate() {
local val=$1
local year month day
if [ ${#val} -ne 8 ]; then
return 255
fi
if [[ ! ${val} =~ ^[0-9][0-9][0-9][0-9][0-1][0-9][0-3][0-9]$ ]];then
return 255
fi
# year=${val:0:4}
month=${val:4:2}
day=${val:6:2}
month=${month#0} # 2桁が前提なので先頭1文字に0があったら削除
day=${day#0} # (同上)
if [ ${month} -lt 1 \
-o ${month} -gt 12 ]; then
return 255
fi
if [ ${day} -lt 1 \
-o ${day} -gt 31 ]; then
return 255
fi
return 0
}
function isNum() {
local val=$1
if [[ ${val} =~ ^[+\-]*[0-9]+$ ]];then
return 0
else
return 255
fi
}
function suppressZero() {
local val=$1
if [[ $val =~ ^(0+)(.*)$ ]]; then
val=${BASH_REMATCH[2]}
fi
echo $val
}
#---------------------------------------------------------------------
#--- main
#---------------------------------------------------------------------
targetDate=""
formatString=""
declare -a deltaVals
deltaVals[0]="";deltaVals[1]="";deltaVals[2]="";
declare -a deltaMessages
deltaMessages[0]="年";deltaMessages[1]="ヶ月";deltaMessages[2]="日";
declare -a units
units[0]="years";units[1]="months";units[2]="days"
while getopts ':T:Y:M:D:h' OPT ; do
case ${OPT} in
T) isDate ${OPTARG}
if [ $? -ne 0 ]; then
echo "-${OPT}には日付を指定してください。"$'\n'
printUsage ${C_SCRIPT_NAME}
exit 255
fi
targetDate=${OPTARG}
;;
Y) isNum ${OPTARG}
if [ $? -ne 0 ]; then
echo "-${OPT}には年数を指定してください。"$'\n'
printUsage ${C_SCRIPT_NAME}
exit 255
fi
deltaVals[0]=${OPTARG}
;;
M) isNum ${OPTARG}
if [ $? -ne 0 ]; then
echo "-${OPT}には月数を指定してください。"$'\n'
printUsage ${C_SCRIPT_NAME}
exit 255
fi
deltaVals[1]=${OPTARG}
;;
D) isNum ${OPTARG}
if [ $? -ne 0 ]; then
echo "-${OPT}には日数を指定してください。"$'\n'
printUsage ${C_SCRIPT_NAME}
exit 255
fi
deltaVals[2]=${OPTARG}
;;
h|*) printUsage ${C_SCRIPT_NAME}
exit 255
;;
esac
done
# 差分のパラメータが指定されない時には"-D 0"として解釈させる
if [ "${deltaVals[0]}" == "" \
-a "${deltaVals[1]}" == "" \
-a "${deltaVals[2]}" == "" ];then
deltaVals[0]="0"
fi
# パラメータを解釈する
valueRaw="";valueNum="";valueAbs="";string=""
message="";formerMessage=""
for (( i=$((${#deltaVals[@]}-1)); i>=0; i-- )) ; do # 降順ループ(日→月→年)
if [ "${deltaVals[${i}]}" != "" ]; then
valueRaw=${deltaVals[${i}]}
case ${valueRaw:0:1} in
-) valueAbs=${valueRaw:1}
valueAbs=`suppressZero ${valueAbs}`
valueNum=$((0-${valueAbs}))
;;
+) valueAbs=${valueRaw:1}
valueAbs=`suppressZero ${valueAbs}`
valueNum=$((${valueAbs}+0))
;;
*) valueAbs=${valueRaw}
valueAbs=`suppressZero ${valueAbs}`
valueNum=$((${valueAbs}+0))
;;
esac
message=${deltaMessages[${i}]}
if [ ${valueNum} -ge 0 ]; then
formatString=${formatString}${valueAbs}" "${units[${i}]}" "
message=${valueAbs}${message}"後"
else
formatString=${formatString}${valueAbs}" "${units[${i}]}" ago "
message=${valueAbs}${message}"前"
fi
if [ "${formerMessage}" != "" ]; then
message=${message}"の、そこから"
fi
formerMessage=${message}
else
message=""
fi
deltaMessages[${i}]=${message}
done
if [ "${targetDate}" == "" ]; then
targetDate="now"
targetDateMessage="起点日付[本日]"
else
targetDateMessage="起点日付"
fi
dateTarget=`date --date "${targetDate}" +%Y/%m/%d`
targetDateMessage=${targetDateMessage}"("${dateTarget}")"
dateTargetCal=${dateTarget//\//-}
dateTargets=(`echo ${dateTarget//\// }`)
dateRaw=${dateTarget##\/}
# 日付を計算する
if [ "${formatString}" != "" ]; then
dateRaw=`date --date "${dateRaw} ${formatString}" +%Y%m%d`
fi
dateResult=`date --date ${dateRaw} +%Y/%m/%d`
dateResultCal=${dateResult//\//-}
dateResults=(`echo ${dateResult//\// }`)
# カレンダー表示(起算日分)
echo "≪${targetDateMessage}のカレンダー≫"
cal ${dateTargets[1]} ${dateTargets[0]} -H ${dateTargetCal}
echo ""
# 結果日付表示
cat <<EOF
あなたが知りたい日付は、
${targetDateMessage}から ${deltaMessages[0]} ${deltaMessages[1]} ${deltaMessages[2]} の
${dateResult}
です
EOF
# カレンダー表示(結果分)
echo "≪${dateResult}のカレンダー≫"
cal ${dateResults[1]} ${dateResults[0]} -H ${dateResultCal}
echo ""
exit 0
calcDate.shの使い方は……
calcDate.sh [ -T 起点とする<日付> ]
[ -Y "年"の<差分値> ] [ -M "月"の<差分値> ] [ -D "日"の<差分値> ]
[ -h ]
<日付> := YYYYMMDD
<差分値> := [+|-] 数値
例1: calcDate.sh -Y 2 -D 10 (本日から)2年と10日後の日付を求める
例2: calcDate.sh -Y -2 -D +10 (本日から)2年前の日付から、更に10日後の日付を求める
例3: calcDate.sh -T 21120903 -Y -100 -D +10 2112/9/3("ドラえもん"の製造日)から100年前の日付から、更に10日後の日付を求める
例4: calcDate.sh -h 使い方(=現在表示してる内容)を表示する
特記事項 -Tのパラメータ指定の無い場合は、当日を起点とする日付として扱う
以上です
オフライン