Skip to content

Instantly share code, notes, and snippets.

@suzuki-kei
Created April 25, 2024 13:49
Show Gist options
  • Save suzuki-kei/cd1b84e56af718fae4d6cd6d07d9ae0e to your computer and use it in GitHub Desktop.
Save suzuki-kei/cd1b84e56af718fae4d6cd6d07d9ae0e to your computer and use it in GitHub Desktop.
work-time
#!/usr/bin/env bash
set -eu -o posix -o pipefail
shopt -s extglob
declare -gr EXIT_STATUS_SUCCESS=0
declare -gr EXIT_STATUS_NO_ARGUMENTS=1
declare -gr EXIT_STATUS_INVALID_FORMAT=2
declare -gr STANDARD_BREAK_TIME_IN_MINUTES=60
declare -gr USAGE=$(cat <<EOS | sed 's/^ //'
NAME
$(basename -- "${0}") -- 一日の労働時間を計算します
SYNOPSIS
$(basename -- "${0}") [OPTION...] [TERM|BREAK_TIME]...
DESCRIPTION
勤務の開始時間, 終了時間, 休憩時間から一日の労働時間を計算します.
TERM
勤務の開始時間と終了時間を指定します.
有効な形式は "HH:MM-HH:MM" または "HHMM-HHMM" です (例: "09:00-18:00", "0900-1800").
BREAK_TIME
途中休憩した時間 (昼休憩以外の休憩時間) を分単位で指定します.
有効な形式は "-M" です (例: "-30").
OPTIONS
-h | --help
このコマンドの使い方を表示します.
EXAMPLES
# 勤務の開始時間と終了時間を指定します
$ $(basename -- "${0}") 09:00-18:00
# 途中休憩した場合は以下のように働いた時間帯を指定します
$ $(basename -- "${0}") 09:00-18:00 19:00-20:00
# 次のように途中休憩の時間を指定しても同じ結果になります
$ $(basename -- "${0}") 09:00-20:00 -60
EOS
)
function main
{
if [[ $# == 0 ]]; then
print_usage
exit ${EXIT_STATUS_NO_ARGUMENTS}
fi
declare work_time_in_minutes=-${STANDARD_BREAK_TIME_IN_MINUTES}
declare break_time_in_minutes=0
for argument in "$@"; do
if [[ "${argument}" == '-h' ]] || [[ "${argument}" == '--help' ]]; then
print_usage
exit ${EXIT_STATUS_SUCCESS}
fi
# 正式には HH:MM-HH:MM 形式と HHMM-HHMM 形式を認める.
# ただし, ゼロ埋めしない形式 (H:MM や HH:M など) も明文化しない機能として許容する.
if [[ "${argument}" =~ ^([0-9][0-9]?):?([0-9][0-9]?)-([0-9][0-9]?):?([0-9][0-9]?)$ ]]; then
declare lower=$(echo "${BASH_REMATCH[1]} * 60 + ${BASH_REMATCH[2]}" | bc)
declare upper=$(echo "${BASH_REMATCH[3]} * 60 + ${BASH_REMATCH[4]}" | bc)
if [[ ${lower} -gt ${upper} ]]; then
upper=$((upper + 24 * 60))
fi
work_time_in_minutes=$((work_time_in_minutes + (upper - lower)))
continue
fi
if [[ "${argument}" =~ ^-([0-9]+)$ ]]; then
work_time_in_minutes=$((work_time_in_minutes - BASH_REMATCH[1]))
break_time_in_minutes=$((break_time_in_minutes + BASH_REMATCH[1]))
continue
fi
echo "Invalid argument: ${argument}" >&2
exit ${EXIT_STATUS_INVALID_FORMAT}
done
declare -r hours=$((work_time_in_minutes / 60))
declare -r minutes=$((work_time_in_minutes % 60))
declare -r work_time="${hours}$(echo "${minutes} / 60" | bc -l | sed -r 's/0+$//')"
echo "労働時間 = ${work_time}H"
echo "昼休憩 = ${STANDARD_BREAK_TIME_IN_MINUTES}min"
echo "途中休憩 = ${break_time_in_minutes}min"
exit ${EXIT_STATUS_SUCCESS}
}
function print_usage
{
echo "${USAGE}"
}
if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then
main "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment