l43_time 0.1.6 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e4bda3b58d2b640b5a2314a056f1e3080f8ae1282c410900b1ba9b1f5af459
4
- data.tar.gz: 2be473abf597a07b7212a17998d13065924bf34e8783e8071cf59575187b36a4
3
+ metadata.gz: a51d17ccbe9e3c6392c3a7739c2745d79e4b7e05791b53f63de5e7d2135ca984
4
+ data.tar.gz: 29ba80c388b3b6473d60bd513233fe77a064d91dce9db76ae7405b11f5e145ff
5
5
  SHA512:
6
- metadata.gz: dcebf38e4b55d2ac034d11a68334cf7da16f64d5cc6ae4f12699b3bf4602a34d430d9bf6c7792c5e860fd2b7fd7ceff3b7f12ad56450dc26782de4e6c6c79d4e
7
- data.tar.gz: 2c2de6d072b43a1cfc79bfcbe39c38b64a5003abcf72d914f0be3b4053d7bdd4e55a12fa8bb903dee978ff7bfe614ace5b447c1fd7fbc18c64bf91697b8db3cc
6
+ metadata.gz: 70f0beb33e0a6620f2d70ae1b68841c432df7adfd1a07f1b70da973e62b989629136971de49272abaee031addcfd26e9c06c63fb42fb2c1995c539623a5402e3
7
+ data.tar.gz: 63025a68db8b283b83eb257268f13ba1c7f12015c70b81ab95e069236ff497928c00229454b4fc9935a7aa912d825f9c94d629e1c6d1adfd2f7547405050a486
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+
3
4
  require_relative 'consts'
4
5
  require_relative 'errors'
5
- require_relative 'tools/scanner'
6
6
  require_relative 'ts'
7
7
 
8
+ require 'l43/time/tools/format_ts'
9
+ require 'l43/time/tools/scanner'
10
+
8
11
  module L43
9
12
  module Time
10
13
  module Parser
@@ -20,6 +23,12 @@ module L43
20
23
  (?<value>[[:digit:]]+ (?:\.[[:digit:]]+)?) [[:space:]]* (?<unit>[[:lower:]]+)
21
24
  }x
22
25
 
26
+ #
27
+
28
+ def format_ts(ts, **opts) = Tools::FormatTs.format_ts(ts, **opts)
29
+
30
+ def format_ts!(ts, **opts) = Tools::FormatTs.format_ts!(ts, **opts)
31
+
23
32
  def parse_duration!(str)
24
33
  case parse_duration(str)
25
34
  in :ok, value
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'l43/core/result'
4
+ require 'l43/open_object'
5
+
6
+ module L43
7
+ module Time
8
+ module Tools
9
+ module FormatTs extend self
10
+ include Core
11
+ class Options
12
+ extend OpenObject
13
+ attributes decs: 1,
14
+ dec_seps: /[.,]/,
15
+ decimal_point: '.',
16
+ fill: true,
17
+ joiner: ':',
18
+ seps: /[-:]/,
19
+ suppress_leading_zeroes: false,
20
+ timestamp: nil
21
+ end
22
+
23
+ def format_ts(ts, **opts)
24
+ options = Options.new(timestamp: ts, **opts)
25
+ ts = ts.strip
26
+ case split_parts(ts, options:)
27
+ in :ok, parts
28
+ format_parts(parts, options:)
29
+ in error
30
+ error
31
+ end
32
+ end
33
+
34
+ def format_ts!(ts, **opts)
35
+ case format_ts(ts, **opts)
36
+ in :ok, value
37
+ value
38
+ in :error, message
39
+ raise BadFormat, message
40
+ end
41
+ end
42
+
43
+
44
+ private
45
+ def check_parts(hs, ms, secs, frac, options)
46
+ culprit = ""
47
+ int_values = [
48
+ [hs, "hours"], [ms, "minutes"], [secs, "seconds"], [frac, "second's decimal part"]]
49
+ .map do |value, name|
50
+ culprit = name
51
+ Integer(value)
52
+ end
53
+ check_range(*int_values, options:)
54
+ rescue ArgumentError => ae
55
+ if ae.message.start_with?("invalid value for Integer():")
56
+ return error_result("invalid integer in #{culprit}", options:)
57
+ end
58
+ raise
59
+ end
60
+
61
+ MAX_ALLOWED_FOR_M_OR_S = 59
62
+ def check_range(hs, ms, secs, frac, options:)
63
+ return error_result("minutes > #{MAX_ALLOWED_FOR_M_OR_S}", options:) if ms > MAX_ALLOWED_FOR_M_OR_S
64
+ return error_result("seconds > #{MAX_ALLOWED_FOR_M_OR_S}", options:) if secs > MAX_ALLOWED_FOR_M_OR_S
65
+
66
+ Result.ok([hs, ms, secs, frac])
67
+ end
68
+
69
+ def convert_and_decimals(parts, options:)
70
+ parts => *hms, secs
71
+ case secs.split(options.dec_seps)
72
+ in [_]
73
+ check_parts(*hms, secs, 0, options)
74
+ in [s, frac]
75
+ check_parts(*hms, s, frac, options)
76
+ else
77
+ error_result("too many decimal points in seconds part", options:)
78
+ end
79
+ end
80
+
81
+ def error_result(message, options:) = Result.error("#{message} in timestamp: #{options.timestamp.inspect}")
82
+
83
+ def format_parts(parts, options:)
84
+ parts =
85
+ parts.drop_while(&:zero?) if options.suppress_leading_zeroes
86
+ parts => *parts, frac
87
+ parts = parts.map { format("%02d", it) } if options.fill
88
+ parts => *parts, seconds
89
+
90
+ seconds = seconds.to_s + options.decimal_point + frac.to_s[0...options.decs]
91
+ Result.ok([*parts, seconds].join(options.joiner))
92
+ end
93
+
94
+ def split_parts(ts, options:)
95
+ return error_result("empty timestamp", options:) if ts.empty?
96
+
97
+ parts =
98
+ case ts.split(options.seps)
99
+ in [secs]
100
+ [0, 0, secs]
101
+ in [mins, secs]
102
+ [0, mins, secs]
103
+ in [_, _, _] => tripple
104
+ tripple
105
+ else
106
+ return error_result("too many parts", options:)
107
+ end
108
+
109
+ convert_and_decimals(parts, options:)
110
+ end
111
+
112
+ end
113
+ end
114
+ end
115
+ end
116
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -2,7 +2,7 @@
2
2
 
3
3
  module L43
4
4
  module Time
5
- VERSION = '0.1.6'
5
+ VERSION = '0.1.7'
6
6
  end
7
7
  end
8
8
  # SPDX-License-Identifier: AGPL-3.0-or-later
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: l43_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-04-01 00:00:00.000000000 Z
10
+ date: 2026-04-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ostruct
@@ -37,6 +37,34 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: 0.2.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: l43_core
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.2.7
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.2.7
54
+ - !ruby/object:Gem::Dependency
55
+ name: l43_open_object
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.2.9
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.2.9
40
68
  description: 'Time related tools
41
69
 
42
70
  '
@@ -56,6 +84,7 @@ files:
56
84
  - lib/l43/time/range.rb
57
85
  - lib/l43/time/time_range.rb
58
86
  - lib/l43/time/to_time.rb
87
+ - lib/l43/time/tools/format_ts.rb
59
88
  - lib/l43/time/tools/map_ok.rb
60
89
  - lib/l43/time/tools/scanner.rb
61
90
  - lib/l43/time/ts.rb
@@ -78,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
107
  - !ruby/object:Gem::Version
79
108
  version: '0'
80
109
  requirements: []
81
- rubygems_version: 4.0.9
110
+ rubygems_version: 4.0.10
82
111
  specification_version: 4
83
112
  summary: Time related tools
84
113
  test_files: []