timecalc-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f0a9f612e928ac76c23ed9465032704fb65e69efa20d19953809d3b5e9f88fd1
4
+ data.tar.gz: b421a1764b820597bf222d4cfa60842035c8eba0124c490da9e0990fa75623f9
5
+ SHA512:
6
+ metadata.gz: 35800c706e05118ff7ccccf4c52e9dfa2fb1633b76441af5650d3ce8cb289acece56cf27d786fc92a6a61025f29e103d46c53c5abc377f930eeccdadc740c23d
7
+ data.tar.gz: b1d5eb7ee8add40bc8f6a0436f0a5e48df995e71bcc6788df4f9cb0056c11c6e75f2ff8c75c17b98f40a34f9b8ca4b31df1badef2376b9e6a6f189d35657554c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,297 @@
1
+ # TimeCalc
2
+
3
+ TimeCalcは、複数の時間帯を入力して、合計時間を計算できるRuby製のコマンドラインツール(CLI)です。
4
+
5
+ **日本語 | [English](#english)**
6
+
7
+ ---
8
+
9
+ ## 日本語
10
+
11
+ ### 機能
12
+
13
+ - 複数の時間帯の合計時間を計算
14
+ - `HH:MM` または `HH` 形式で時刻を指定可能
15
+ - 各時間帯の経過時間と合計時間を表示
16
+ - `--hm` で標準入力の時間・分データを縦に合計
17
+ - 不正な入力は標準エラー出力に表示し、終了コード `1` で終了
18
+
19
+ ### インストール
20
+
21
+ Rubyがインストールされている環境で、以下を実行してください。
22
+
23
+ ```bash
24
+ gem install timecalc-cli
25
+ ```
26
+
27
+ ※ RubyGems.orgへの公開後に利用できます。
28
+
29
+ ### 使い方
30
+
31
+ 複数の時間帯をカンマ区切りで指定します。
32
+
33
+ ```bash
34
+ timecalc "11:17-12, 12:30-13, 13:15-14, 15:30-18"
35
+ ```
36
+
37
+ 実行結果:
38
+
39
+ ```text
40
+ 11:17 - 12 : 0時間43分
41
+ 12:30 - 13 : 0時間30分
42
+ 13:15 - 14 : 0時間45分
43
+ 15:30 - 18 : 2時間30分
44
+ --------------------------
45
+ 合計:4時間28分
46
+ ```
47
+
48
+ 分を省略した場合は、0分として扱います。
49
+
50
+ ```bash
51
+ timecalc "11-12, 13-15"
52
+ ```
53
+
54
+ 実行結果:
55
+
56
+ ```text
57
+ 11 - 12 : 1時間0分
58
+ 13 - 15 : 2時間0分
59
+ --------------------------
60
+ 合計:3時間0分
61
+ ```
62
+
63
+ ### 時間・分を縦に合計する(`--hm`)
64
+
65
+ `--hm` を指定すると、標準入力から1行につき1件の経過時間を受け取り、EOF(Ctrl+D)で合計を表示します。
66
+
67
+ ```bash
68
+ timecalc --hm
69
+ 6.15
70
+ 8.4
71
+ 7.7
72
+ # Ctrl+D
73
+ ```
74
+
75
+ ```text
76
+ 合計:21時間26分
77
+ ```
78
+
79
+ ファイルからの入力にも対応しています。
80
+
81
+ ```bash
82
+ timecalc --hm < times.txt
83
+ ```
84
+
85
+ `6.15` は6時間15分を表します。これは小数ではなく、ピリオドの前を時間、後ろを分として扱います。
86
+
87
+ ### 入力ルール
88
+
89
+ - 時刻は2桁の `HH` または `HH:MM` 形式で指定します。
90
+ - 時は `00`〜`23`、分は `00`〜`59` の範囲です。
91
+ - 開始時刻は終了時刻以前にしてください。同じ時刻は0分として計算されます。
92
+ - 日付をまたぐ時間帯には対応していません。
93
+ - すべての時間帯を検証してから計算結果を表示します。不正な入力では結果を表示せず、標準エラー出力にエラーメッセージを表示して終了コード `1` で終了します。
94
+
95
+ ### `--hm` の入力ルール
96
+
97
+ - 1行につき、非負の `H` または `H.MM` 形式で1件の経過時間を指定します。時間部分は24時間以上でも指定できます。
98
+ - 分は `0`〜`59` の範囲です。`8.4`、`7.5`、`0.3`、`8.04` はそれぞれ8時間4分、7時間5分、0時間3分、8時間4分を表します。
99
+ - 空行は無視します。負の数、文字列、不正な書式、範囲外の分はエラーになります。
100
+ - 不正な行がある場合は、行番号を含むエラーを標準エラー出力に表示し、合計は表示しません。
101
+
102
+ ### オプション
103
+
104
+ ```bash
105
+ timecalc --help
106
+ timecalc --version
107
+ timecalc --hm
108
+ ```
109
+
110
+ ### 開発方法
111
+
112
+ リポジトリをクローンし、依存ライブラリをインストールします。
113
+
114
+ ```bash
115
+ git clone https://github.com/<username>/timecalc.git
116
+ cd timecalc
117
+ bundle install
118
+ ```
119
+
120
+ ローカルで実行します。
121
+
122
+ ```bash
123
+ bundle exec ruby bin/timecalc "11-12, 13-15"
124
+ ```
125
+
126
+ テストを実行します。
127
+
128
+ ```bash
129
+ bundle exec rspec
130
+ ```
131
+
132
+ Gemをビルドします。
133
+
134
+ ```bash
135
+ gem build timecalc-cli.gemspec
136
+ ```
137
+
138
+ ビルドしたGemをローカルにインストールします。
139
+
140
+ ```bash
141
+ gem install ./timecalc-cli-0.1.0.gem
142
+ ```
143
+
144
+ ### 動作環境
145
+
146
+ - Ruby 3.1以上
147
+
148
+ ### ライセンス
149
+
150
+ MIT License
151
+
152
+ ---
153
+
154
+ ## English
155
+
156
+ TimeCalc is a Ruby command-line tool (CLI) that calculates the total duration of multiple time ranges.
157
+
158
+ ### Features
159
+
160
+ - Calculate the total duration of multiple time ranges
161
+ - Support `HH:MM` and `HH` time formats
162
+ - Display individual durations and the total duration
163
+ - Sum line-oriented hours-and-minutes input from standard input with `--hm`
164
+ - Print invalid-input errors to standard error and exit with status `1`
165
+
166
+ ### Installation
167
+
168
+ Run the following command in an environment with Ruby installed.
169
+
170
+ ```bash
171
+ gem install timecalc-cli
172
+ ```
173
+
174
+ _This command will be available after the gem is published to RubyGems.org._
175
+
176
+ ### Usage
177
+
178
+ Pass multiple time ranges separated by commas.
179
+
180
+ ```bash
181
+ timecalc "11:17-12, 12:30-13, 13:15-14, 15:30-18"
182
+ ```
183
+
184
+ Output:
185
+
186
+ ```text
187
+ 11:17 - 12 : 0時間43分
188
+ 12:30 - 13 : 0時間30分
189
+ 13:15 - 14 : 0時間45分
190
+ 15:30 - 18 : 2時間30分
191
+ --------------------------
192
+ 合計:4時間28分
193
+ ```
194
+
195
+ If minutes are omitted, they are treated as `00`.
196
+
197
+ ```bash
198
+ timecalc "11-12, 13-15"
199
+ ```
200
+
201
+ Output:
202
+
203
+ ```text
204
+ 11 - 12 : 1時間0分
205
+ 13 - 15 : 2時間0分
206
+ --------------------------
207
+ 合計:3時間0分
208
+ ```
209
+
210
+ ### Sum line-oriented hours and minutes (`--hm`)
211
+
212
+ With `--hm`, enter one elapsed duration per line through standard input. End input with EOF (Ctrl+D) to print the total.
213
+
214
+ ```bash
215
+ timecalc --hm
216
+ 6.15
217
+ 8.4
218
+ 7.7
219
+ # Ctrl+D
220
+ ```
221
+
222
+ ```text
223
+ 合計:21時間26分
224
+ ```
225
+
226
+ Input redirection is also supported:
227
+
228
+ ```bash
229
+ timecalc --hm < times.txt
230
+ ```
231
+
232
+ `6.15` means 6 hours and 15 minutes. It is not a decimal value: the portion before the period is hours and the portion after it is minutes.
233
+
234
+ ### Input rules
235
+
236
+ - Times must use the two-digit `HH` or `HH:MM` format.
237
+ - Hours must be from `00` to `23`; minutes must be from `00` to `59`.
238
+ - The start time must be no later than the end time. Equal times count as zero minutes.
239
+ - Time ranges that cross midnight are not supported.
240
+ - All ranges are validated before any results are printed. Invalid input prints an error to standard error and exits with status `1` without printing results.
241
+
242
+ ### `--hm` input rules
243
+
244
+ - Enter one non-negative elapsed duration per line in `H` or `H.MM` format. The hour portion may be 24 or greater.
245
+ - Minutes must be from `0` to `59`. `8.4`, `7.5`, `0.3`, and `8.04` mean 8 hours 4 minutes, 7 hours 5 minutes, 0 hours 3 minutes, and 8 hours 4 minutes, respectively.
246
+ - Blank lines are ignored. Negative values, text, malformed values, and out-of-range minutes are errors.
247
+ - If any line is invalid, an error including its line number is printed to standard error and no total is printed.
248
+
249
+ ### Options
250
+
251
+ ```bash
252
+ timecalc --help
253
+ timecalc --version
254
+ timecalc --hm
255
+ ```
256
+
257
+ ### Development
258
+
259
+ Clone the repository and install dependencies.
260
+
261
+ ```bash
262
+ git clone https://github.com/<username>/timecalc.git
263
+ cd timecalc
264
+ bundle install
265
+ ```
266
+
267
+ Run locally:
268
+
269
+ ```bash
270
+ bundle exec ruby bin/timecalc "11-12, 13-15"
271
+ ```
272
+
273
+ Run tests:
274
+
275
+ ```bash
276
+ bundle exec rspec
277
+ ```
278
+
279
+ Build the gem:
280
+
281
+ ```bash
282
+ gem build timecalc-cli.gemspec
283
+ ```
284
+
285
+ Install the gem locally:
286
+
287
+ ```bash
288
+ gem install ./timecalc-cli-0.1.0.gem
289
+ ```
290
+
291
+ ### Requirements
292
+
293
+ - Ruby 3.1 or later
294
+
295
+ ### License
296
+
297
+ MIT License
data/bin/timecalc ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/timecalc_cli"
5
+
6
+ exit TimecalcCLI.run(ARGV)
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimecalcCLI
4
+ VERSION = "0.1.0"
5
+ TIME_PATTERN = /\A\d{2}(?::\d{2})?\z/
6
+ RANGE_PATTERN = /\A(?<start>\d{2}(?::\d{2})?)-(?<finish>\d{2}(?::\d{2})?)\z/
7
+ HM_PATTERN = /\A(?<hours>\d+)(?:\.(?<minutes>\d{1,2}))?\z/
8
+ ParsedRange = Struct.new(:start_label, :end_label, :duration, keyword_init: true)
9
+
10
+ class InputError < StandardError; end
11
+
12
+ def self.run(args, input: $stdin, output: $stdout, error: $stderr)
13
+ case args
14
+ when []
15
+ output.puts help
16
+ return 0
17
+ when ["--help"]
18
+ output.puts help
19
+ return 0
20
+ when ["--version"]
21
+ output.puts VERSION
22
+ return 0
23
+ when ["--hm"]
24
+ return run_hm(input, output)
25
+ end
26
+
27
+ ranges = parse_ranges(args.join(" "))
28
+ print_result(ranges, output)
29
+ 0
30
+ rescue InputError => e
31
+ error.puts "エラー: #{e.message}"
32
+ 1
33
+ end
34
+
35
+ def self.run_hm(input, output)
36
+ total_minutes = parse_hm_entries(input).sum
37
+ output.puts "合計:#{format_duration(total_minutes)}"
38
+ 0
39
+ end
40
+
41
+ def self.parse_hm_entries(input)
42
+ input.each_line.with_index(1).filter_map do |line, line_number|
43
+ value = line.strip
44
+ next if value.empty?
45
+
46
+ parse_hm_entry(value, line_number)
47
+ end
48
+ end
49
+
50
+ def self.parse_hm_entry(value, line_number)
51
+ match = HM_PATTERN.match(value)
52
+ unless match
53
+ raise InputError, "行 #{line_number}: 時間は H または H.MM 形式で指定してください: #{value.inspect}"
54
+ end
55
+
56
+ hours = match[:hours].to_i
57
+ minutes = match[:minutes]&.to_i || 0
58
+
59
+ unless minutes.between?(0, 59)
60
+ raise InputError, "行 #{line_number}: 分は 0〜59 の範囲で指定してください: #{value.inspect}"
61
+ end
62
+
63
+ (hours * 60) + minutes
64
+ end
65
+
66
+ def self.parse_ranges(input)
67
+ ranges = input.split(",", -1).map(&:strip)
68
+ raise InputError, "時間帯を指定してください。" if ranges.empty? || ranges.any?(&:empty?)
69
+
70
+ ranges.map { |range| parse_range(range) }
71
+ end
72
+
73
+ def self.parse_range(range)
74
+ match = RANGE_PATTERN.match(range)
75
+ raise InputError, "時間帯は HH-HH または HH:MM-HH:MM 形式で指定してください: #{range}" unless match
76
+
77
+ start_label = match[:start]
78
+ end_label = match[:finish]
79
+ start_minutes = to_minutes(start_label)
80
+ end_minutes = to_minutes(end_label)
81
+
82
+ if start_minutes > end_minutes
83
+ raise InputError, "開始時刻は終了時刻以前にしてください(日付をまたぐ時間帯には対応していません): #{range}"
84
+ end
85
+
86
+ ParsedRange.new(
87
+ start_label: start_label,
88
+ end_label: end_label,
89
+ duration: end_minutes - start_minutes
90
+ )
91
+ end
92
+
93
+ def self.to_minutes(time)
94
+ raise InputError, "時刻は HH または HH:MM 形式で指定してください: #{time}" unless TIME_PATTERN.match?(time)
95
+
96
+ hours, minutes = time.split(":").map(&:to_i)
97
+ minutes ||= 0
98
+
99
+ unless hours.between?(0, 23) && minutes.between?(0, 59)
100
+ raise InputError, "時刻は 00:00 から 23:59 の範囲で指定してください: #{time}"
101
+ end
102
+
103
+ hours * 60 + minutes
104
+ end
105
+
106
+ def self.format_duration(total_minutes)
107
+ hours, minutes = total_minutes.divmod(60)
108
+ "#{hours}時間#{minutes}分"
109
+ end
110
+
111
+ def self.print_result(ranges, output)
112
+ total_minutes = ranges.sum(&:duration)
113
+
114
+ ranges.each do |range|
115
+ output.puts "#{range.start_label} - #{range.end_label} : #{format_duration(range.duration)}"
116
+ end
117
+
118
+ output.puts "--------------------------"
119
+ output.puts "合計:#{format_duration(total_minutes)}"
120
+ end
121
+
122
+ def self.help
123
+ <<~HELP.chomp
124
+ 使い方:
125
+ timecalc "HH-HH, HH:MM-HH:MM"
126
+ timecalc --hm
127
+
128
+ 複数の時間帯をカンマ区切りで指定します。
129
+ 時刻は 00〜23 時、00〜59 分の範囲で指定してください。
130
+ 日付をまたぐ時間帯には対応していません。
131
+
132
+ --hm は標準入力から 1 行につき H または H.MM 形式の経過時間を受け取り、EOF で合計を表示します。
133
+ HELP
134
+ end
135
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "timecalc/cli"
metadata ADDED
@@ -0,0 +1,43 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timecalc-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eli
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Calculate total duration from multiple time ranges.
13
+ executables:
14
+ - timecalc
15
+ extensions: []
16
+ extra_rdoc_files: []
17
+ files:
18
+ - LICENSE
19
+ - README.md
20
+ - bin/timecalc
21
+ - lib/timecalc/cli.rb
22
+ - lib/timecalc_cli.rb
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 4.0.10
41
+ specification_version: 4
42
+ summary: A simple CLI time calculator
43
+ test_files: []