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 +4 -4
- data/lib/l43/time/parser.rb +10 -1
- data/lib/l43/time/tools/format_ts.rb +116 -0
- data/lib/l43/time/version.rb +1 -1
- metadata +32 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a51d17ccbe9e3c6392c3a7739c2745d79e4b7e05791b53f63de5e7d2135ca984
|
|
4
|
+
data.tar.gz: 29ba80c388b3b6473d60bd513233fe77a064d91dce9db76ae7405b11f5e145ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70f0beb33e0a6620f2d70ae1b68841c432df7adfd1a07f1b70da973e62b989629136971de49272abaee031addcfd26e9c06c63fb42fb2c1995c539623a5402e3
|
|
7
|
+
data.tar.gz: 63025a68db8b283b83eb257268f13ba1c7f12015c70b81ab95e069236ff497928c00229454b4fc9935a7aa912d825f9c94d629e1c6d1adfd2f7547405050a486
|
data/lib/l43/time/parser.rb
CHANGED
|
@@ -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
|
data/lib/l43/time/version.rb
CHANGED
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.
|
|
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-
|
|
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.
|
|
110
|
+
rubygems_version: 4.0.10
|
|
82
111
|
specification_version: 4
|
|
83
112
|
summary: Time related tools
|
|
84
113
|
test_files: []
|