What: 新增 jsc-log:report,把工作日誌總結成年報、月報、週報或日報,寫進 wiki REPORT_{HASH}。另加 tools/report-range.sh 算期間、tools/report-template.sh 解析範本,以及四份報表範本與報表目錄範本。
Why: worklog 只記單筆工作,累積起來沒有工具看得出一週或一個月做了什麼、什麼在卡。要總結只能自己翻頁面加總。
How: 期間換算交給系統的 date,不自己算閏年與週界;週次採 ISO-8601。範本解析採工作目錄優先,.jsc/templates/report-{period}.md 蓋過技能自帶的那份,專案要換格式不必改技能。資料讀 LOG_CONTENTS 列出的所有日誌頁,取工作日期落在期間內的條目,只加總條目真的寫了的數字。
Who: 工作日誌的期間總結。
76 lines
2.6 KiB
Bash
Executable File
76 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
# report-range.sh — 算出報表期間的起訖日期與標籤(供 jsc-log:report 呼叫)。
|
||
# 用法:
|
||
# report-range.sh {daily|weekly|monthly|yearly} [基準日期 yyyy-MM-dd]
|
||
# 基準日期省略時用今天。輸出一行 TSV:
|
||
# {start}<TAB>{end}<TAB>{label}<TAB>{period}
|
||
# start、end 皆為 yyyy-MM-dd,含頭含尾。
|
||
# label:daily=2026-08-26、weekly=2026-W35、monthly=2026-08、yearly=2026
|
||
#
|
||
# 週的定義採 ISO-8601:週一起算、週日結束,標籤用 ISO 週次。worklog 頁內以工作週的
|
||
# 週五整理內容,週次與那個週五落在同一週,兩邊對得起來。
|
||
#
|
||
# 日期運算優先用 GNU date -d,退回 BSD date -v。兩者都不支援就 exit 4,不自己算閏年:
|
||
# 手刻日期運算出錯的方式很安靜,報表會少算一天而沒有人發現。
|
||
#
|
||
# 結束碼: 0=成功 2=用法錯誤 4=系統的 date 不支援日期運算
|
||
set -eu
|
||
|
||
usage() {
|
||
echo "用法:report-range.sh {daily|weekly|monthly|yearly} [yyyy-MM-dd]" >&2
|
||
exit 2
|
||
}
|
||
|
||
period="${1:-}"
|
||
case "$period" in daily|weekly|monthly|yearly) ;; *) usage ;; esac
|
||
|
||
base="${2:-}"
|
||
if [ -z "$base" ]; then
|
||
base=$(date +%Y-%m-%d)
|
||
else
|
||
case "$base" in
|
||
[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) ;;
|
||
*) echo "基準日期格式要是 yyyy-MM-dd:$base" >&2; exit 2 ;;
|
||
esac
|
||
fi
|
||
|
||
# $1=基準日 $2=偏移(例 -3 days、+1 month)$3=輸出格式
|
||
shift_date() {
|
||
if date -d "$1 $2" "+$3" >/dev/null 2>&1; then
|
||
date -d "$1 $2" "+$3"
|
||
return 0
|
||
fi
|
||
# BSD:偏移寫法不同(-v-3d),只轉換這裡真的用到的幾種
|
||
_bsd=$(printf '%s' "$2" | sed 's/ days\{0,1\}/d/; s/ months\{0,1\}/m/; s/ years\{0,1\}/y/; s/^+/+/')
|
||
if date -j -f %Y-%m-%d -v"$_bsd" "$1" "+$3" >/dev/null 2>&1; then
|
||
date -j -f %Y-%m-%d -v"$_bsd" "$1" "+$3"
|
||
return 0
|
||
fi
|
||
echo "系統的 date 不支援日期運算,算不出報表期間" >&2
|
||
exit 4
|
||
}
|
||
|
||
fmt() { shift_date "$1" "+0 days" "$2"; }
|
||
|
||
case "$period" in
|
||
daily)
|
||
start="$base"; end="$base"
|
||
label=$(fmt "$base" %Y-%m-%d) ;;
|
||
weekly)
|
||
# ISO 週:週一為第 1 天。%u 給 1(週一)到 7(週日)。
|
||
dow=$(fmt "$base" %u)
|
||
start=$(shift_date "$base" "-$((dow - 1)) days" %Y-%m-%d)
|
||
end=$(shift_date "$start" "+6 days" %Y-%m-%d)
|
||
label=$(fmt "$base" %G-W%V) ;;
|
||
monthly)
|
||
start=$(fmt "$base" %Y-%m-01)
|
||
end=$(shift_date "$(shift_date "$start" "+1 month" %Y-%m-%d)" "-1 day" %Y-%m-%d)
|
||
label=$(fmt "$base" %Y-%m) ;;
|
||
yearly)
|
||
start=$(fmt "$base" %Y-01-01)
|
||
end=$(fmt "$base" %Y-12-31)
|
||
label=$(fmt "$base" %Y) ;;
|
||
esac
|
||
|
||
printf '%s\t%s\t%s\t%s\n' "$start" "$end" "$label" "$period"
|