football-timezones 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +2 -0
- data/lib/football-timezones/datasets.rb +48 -0
- data/lib/football-timezones/timezones.rb +154 -0
- data/lib/football-timezones/version.rb +1 -1
- data/lib/football-timezones.rb +11 -157
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d8574fc2a4c6312eb5f3080f41b1f08a353618b65f049876b2d1c90752e1f579
|
|
4
|
+
data.tar.gz: 001a40fbd239ab29c44104f1c67e1f033a4389974ce5699ffd9f61ce44e193a7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 80ff25b583304c98bd7fac3b838b901010d6d8a44142c9f8cc5a73d69a86c36d5aed47ab9426875fa7d7d8d8036c35b95fb9520e1aae2c91b4589cdd77df4220
|
|
7
|
+
data.tar.gz: 7bf0cf0736dea5c94427049d48a7693e19bc2a6230055a78b759ee12e5df3fcca7282c5ce763c3d2de91bdf31c7fee52e83939bb45ca616a21cd868d85e9d9eb
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
|
@@ -10,5 +10,7 @@ config/timezones_middle_east.csv
|
|
|
10
10
|
config/timezones_pacific.csv
|
|
11
11
|
config/timezones_world.csv
|
|
12
12
|
lib/football-timezones.rb
|
|
13
|
+
lib/football-timezones/datasets.rb
|
|
14
|
+
lib/football-timezones/timezones.rb
|
|
13
15
|
lib/football-timezones/version.rb
|
|
14
16
|
lib/football/timezones.rb
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
module Datasets
|
|
4
|
+
def self.parse_args( args )
|
|
5
|
+
### split args in datasets with leagues and seasons
|
|
6
|
+
datasets = []
|
|
7
|
+
args.each do |arg|
|
|
8
|
+
if arg =~ %r{^[0-9/-]+$} ## season
|
|
9
|
+
if datasets.empty?
|
|
10
|
+
puts "!! ERROR - league required before season arg; sorry"
|
|
11
|
+
exit 1
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
season = Season.parse( arg ) ## check season
|
|
15
|
+
datasets[-1][1] << season
|
|
16
|
+
else ## assume league key
|
|
17
|
+
key = arg.downcase
|
|
18
|
+
datasets << [key, []]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
datasets
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def self.parse( txt )
|
|
26
|
+
### split args in datasets with leagues and seasons
|
|
27
|
+
datasets = []
|
|
28
|
+
recs = parse_csv( txt )
|
|
29
|
+
recs.each do |rec|
|
|
30
|
+
key = rec['league'].downcase
|
|
31
|
+
datasets << [key, []]
|
|
32
|
+
|
|
33
|
+
seasons_str = rec['seasons']
|
|
34
|
+
seasons = seasons_str.split( /[ ]+/ )
|
|
35
|
+
|
|
36
|
+
seasons.each do |season_str|
|
|
37
|
+
season = Season.parse( season_str ) ## check season
|
|
38
|
+
datasets[-1][1] << season
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
datasets
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.read( path )
|
|
45
|
+
parse( read_text( path ))
|
|
46
|
+
end
|
|
47
|
+
end # module Datasets
|
|
48
|
+
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
####
|
|
2
|
+
### check - nest CET class inside UTC e.g. UTC::CET - why? why not?
|
|
3
|
+
## make UTC and CET into a module (not class) - why? why not?
|
|
4
|
+
|
|
5
|
+
module CET ## central european time helpers
|
|
6
|
+
def self.now() zone.now; end
|
|
7
|
+
def self.today() now.to_date; end
|
|
8
|
+
def self.strptime( str, format )
|
|
9
|
+
|
|
10
|
+
### fix - change to Time.strptime - why? why not?
|
|
11
|
+
## (simply) ignore offset; double check that hours, minutes
|
|
12
|
+
## get parsed as is (without applying offset)
|
|
13
|
+
|
|
14
|
+
d = DateTime.strptime( str, format )
|
|
15
|
+
## remove assert check - why? why not?
|
|
16
|
+
if d.zone != '+00:00' ### use d.offset != Ration(0,1) - why? why not?
|
|
17
|
+
puts "!! ASSERT - CET parse date; DateTime returns offset != +0:00"
|
|
18
|
+
pp d.zone
|
|
19
|
+
pp d
|
|
20
|
+
exit 1
|
|
21
|
+
end
|
|
22
|
+
zone.local_time( d.year, d.month, d.day, d.hour, d.min, d.sec )
|
|
23
|
+
end
|
|
24
|
+
def self.zone() @zone ||= UTC.find_zone( 'Europe/Vienna' ); end
|
|
25
|
+
end # class CET
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
module UTC
|
|
30
|
+
def self.now() Time.now.utc; end
|
|
31
|
+
def self.today() now.to_date; end
|
|
32
|
+
|
|
33
|
+
## -- todo - make sure / assert it's always utc - how???
|
|
34
|
+
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
|
35
|
+
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
|
36
|
+
## use to parse utc
|
|
37
|
+
## quick hack -
|
|
38
|
+
## use to_time.getutc instead of utc ???
|
|
39
|
+
def self.strptime( str, format )
|
|
40
|
+
d = DateTime.strptime( str, format )
|
|
41
|
+
## remove assert check - why? why not?
|
|
42
|
+
if d.zone != '+00:00' ### use d.offset != Ration(0,1) - why? why not?
|
|
43
|
+
puts "!! ASSERT - UTC parse date; DateTime returns offset != +0:00"
|
|
44
|
+
pp d.zone
|
|
45
|
+
pp d
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
## note - ignores offset if any !!!!
|
|
49
|
+
## todo/check - report warn if offset different from 0:00 (0/1) - why? why not?
|
|
50
|
+
Time.utc( d.year, d.month, d.day, d.hour, d.min, d.sec )
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.find_zone( name )
|
|
54
|
+
zone = TZInfo::Timezone.get( name )
|
|
55
|
+
## wrap tzinfo timezone in our own - for adding more (auto)checks etc.
|
|
56
|
+
zone ? Timezone.new( zone ) : nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Timezone ## nested inside UTC
|
|
60
|
+
## todo/fix
|
|
61
|
+
## cache timezone - why? why not?
|
|
62
|
+
def initialize( zone )
|
|
63
|
+
@zone = zone
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def to_local( time )
|
|
67
|
+
## assert time is Time (not Date or DateTIme)
|
|
68
|
+
## and assert utc!!!
|
|
69
|
+
assert( time.is_a?( Time ), "time #{time} is NOT of class Time; got #{time.class.name}" )
|
|
70
|
+
assert( time.utc?, "time #{time} is NOT utc; utc? returns #{time.utc?}" )
|
|
71
|
+
local = @zone.to_local( time )
|
|
72
|
+
local
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def local_time( year, month=1, mday=1, hour=0, min=0, sec=0 )
|
|
76
|
+
## add auto-fix for ambigious time (dst vs non-dst)
|
|
77
|
+
## always select first for now (that is, dst)
|
|
78
|
+
@zone.local_time( year, month, mday, hour, min, sec ) {|time| time.first }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def now() @zone.now; end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def assert( cond, msg )
|
|
87
|
+
if cond
|
|
88
|
+
# do nothing
|
|
89
|
+
else
|
|
90
|
+
puts "!!! assert failed - #{msg}"
|
|
91
|
+
exit 1
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end # class Timezone
|
|
95
|
+
end # module UTC
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
module TimezoneHelper
|
|
101
|
+
def find_zone!( league:, season: )
|
|
102
|
+
## note: do NOT pass in league struct! pass in key (string)
|
|
103
|
+
raise ArgumentError, "league key as string|symbol expected" unless league.is_a?(String) || league.is_a?(Symbol)
|
|
104
|
+
|
|
105
|
+
@zones ||= begin
|
|
106
|
+
zones = {}
|
|
107
|
+
['timezones_africa',
|
|
108
|
+
'timezones_america',
|
|
109
|
+
'timezones_asia',
|
|
110
|
+
'timezones_europe',
|
|
111
|
+
'timezones_middle_east',
|
|
112
|
+
'timezones_pacific',
|
|
113
|
+
'timezones_world',].each do |name|
|
|
114
|
+
recs = read_csv( "#{SportDb::Module::Timezones.root}/config/#{name}.csv" )
|
|
115
|
+
recs.each do |rec|
|
|
116
|
+
zone = UTC.find_zone( rec['zone'] )
|
|
117
|
+
if zone.nil?
|
|
118
|
+
## raise ArgumentError - invalid zone
|
|
119
|
+
puts "!! ERROR - cannot find timezone in timezone db:"
|
|
120
|
+
pp rec
|
|
121
|
+
exit 1
|
|
122
|
+
end
|
|
123
|
+
zones[ rec['key']] = zone
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
zones
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
## lookup first try by league+season
|
|
130
|
+
league_code = league.to_s.downcase
|
|
131
|
+
season = Season( season )
|
|
132
|
+
|
|
133
|
+
## e.g. world+2022, etc.
|
|
134
|
+
key = "#{league_code}+#{season}"
|
|
135
|
+
zone = @zones[key]
|
|
136
|
+
|
|
137
|
+
## try league e.g. eng.1 etc.
|
|
138
|
+
zone = @zones[league_code] if zone.nil?
|
|
139
|
+
|
|
140
|
+
## try first code only (country code )
|
|
141
|
+
if zone.nil?
|
|
142
|
+
code, _ = league_code.split( '.', 2 )
|
|
143
|
+
zone = @zones[code]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
if zone.nil? ## still not found; report error
|
|
147
|
+
puts "!! ERROR: no timezone found for #{league} #{season}"
|
|
148
|
+
exit 1
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
zone
|
|
152
|
+
end
|
|
153
|
+
end # module TimezoneHelper
|
|
154
|
+
|
data/lib/football-timezones.rb
CHANGED
|
@@ -7,170 +7,24 @@ require 'tzinfo'
|
|
|
7
7
|
|
|
8
8
|
## our own code
|
|
9
9
|
require_relative 'football-timezones/version'
|
|
10
|
-
|
|
10
|
+
require_relative 'football-timezones/timezones'
|
|
11
11
|
|
|
12
12
|
####
|
|
13
|
-
###
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
module CET ## central european time helpers
|
|
17
|
-
def self.now() zone.now; end
|
|
18
|
-
def self.today() now.to_date; end
|
|
19
|
-
def self.strptime( str, format )
|
|
20
|
-
|
|
21
|
-
### fix - change to Time.strptime - why? why not?
|
|
22
|
-
## (simply) ignore offset; double check that hours, minutes
|
|
23
|
-
## get parsed as is (without applying offset)
|
|
24
|
-
|
|
25
|
-
d = DateTime.strptime( str, format )
|
|
26
|
-
## remove assert check - why? why not?
|
|
27
|
-
if d.zone != '+00:00' ### use d.offset != Ration(0,1) - why? why not?
|
|
28
|
-
puts "!! ASSERT - CET parse date; DateTime returns offset != +0:00"
|
|
29
|
-
pp d.zone
|
|
30
|
-
pp d
|
|
31
|
-
exit 1
|
|
32
|
-
end
|
|
33
|
-
zone.local_time( d.year, d.month, d.day, d.hour, d.min, d.sec )
|
|
34
|
-
end
|
|
35
|
-
def self.zone() @zone ||= UTC.find_zone( 'Europe/Vienna' ); end
|
|
36
|
-
end # class CET
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
module UTC
|
|
41
|
-
def self.now() Time.now.utc; end
|
|
42
|
-
def self.today() now.to_date; end
|
|
43
|
-
|
|
44
|
-
## -- todo - make sure / assert it's always utc - how???
|
|
45
|
-
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
|
46
|
-
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
|
47
|
-
## use to parse utc
|
|
48
|
-
## quick hack -
|
|
49
|
-
## use to_time.getutc instead of utc ???
|
|
50
|
-
def self.strptime( str, format )
|
|
51
|
-
d = DateTime.strptime( str, format )
|
|
52
|
-
## remove assert check - why? why not?
|
|
53
|
-
if d.zone != '+00:00' ### use d.offset != Ration(0,1) - why? why not?
|
|
54
|
-
puts "!! ASSERT - UTC parse date; DateTime returns offset != +0:00"
|
|
55
|
-
pp d.zone
|
|
56
|
-
pp d
|
|
57
|
-
exit 1
|
|
58
|
-
end
|
|
59
|
-
## note - ignores offset if any !!!!
|
|
60
|
-
## todo/check - report warn if offset different from 0:00 (0/1) - why? why not?
|
|
61
|
-
Time.utc( d.year, d.month, d.day, d.hour, d.min, d.sec )
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def self.find_zone( name )
|
|
65
|
-
zone = TZInfo::Timezone.get( name )
|
|
66
|
-
## wrap tzinfo timezone in our own - for adding more (auto)checks etc.
|
|
67
|
-
zone ? Timezone.new( zone ) : nil
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
class Timezone ## nested inside UTC
|
|
71
|
-
## todo/fix
|
|
72
|
-
## cache timezone - why? why not?
|
|
73
|
-
def initialize( zone )
|
|
74
|
-
@zone = zone
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def to_local( time )
|
|
78
|
-
## assert time is Time (not Date or DateTIme)
|
|
79
|
-
## and assert utc!!!
|
|
80
|
-
assert( time.is_a?( Time ), "time #{time} is NOT of class Time; got #{time.class.name}" )
|
|
81
|
-
assert( time.utc?, "time #{time} is NOT utc; utc? returns #{time.utc?}" )
|
|
82
|
-
local = @zone.to_local( time )
|
|
83
|
-
local
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def local_time( year, month=1, mday=1, hour=0, min=0, sec=0 )
|
|
87
|
-
## add auto-fix for ambigious time (dst vs non-dst)
|
|
88
|
-
## always select first for now (that is, dst)
|
|
89
|
-
@zone.local_time( year, month, mday, hour, min, sec ) {|time| time.first }
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def now() @zone.now; end
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def assert( cond, msg )
|
|
98
|
-
if cond
|
|
99
|
-
# do nothing
|
|
100
|
-
else
|
|
101
|
-
puts "!!! assert failed - #{msg}"
|
|
102
|
-
exit 1
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end # class Timezone
|
|
106
|
-
end # module UTC
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
module TimezoneHelper
|
|
112
|
-
def find_zone!( league:, season: )
|
|
113
|
-
## note: do NOT pass in league struct! pass in key (string)
|
|
114
|
-
raise ArgumentError, "league key as string|symbol expected" unless league.is_a?(String) || league.is_a?(Symbol)
|
|
115
|
-
|
|
116
|
-
@zones ||= begin
|
|
117
|
-
zones = {}
|
|
118
|
-
['timezones_africa',
|
|
119
|
-
'timezones_america',
|
|
120
|
-
'timezones_asia',
|
|
121
|
-
'timezones_europe',
|
|
122
|
-
'timezones_middle_east',
|
|
123
|
-
'timezones_pacific',
|
|
124
|
-
'timezones_world',].each do |name|
|
|
125
|
-
recs = read_csv( "#{SportDb::Module::Timezones.root}/config/#{name}.csv" )
|
|
126
|
-
recs.each do |rec|
|
|
127
|
-
zone = UTC.find_zone( rec['zone'] )
|
|
128
|
-
if zone.nil?
|
|
129
|
-
## raise ArgumentError - invalid zone
|
|
130
|
-
puts "!! ERROR - cannot find timezone in timezone db:"
|
|
131
|
-
pp rec
|
|
132
|
-
exit 1
|
|
133
|
-
end
|
|
134
|
-
zones[ rec['key']] = zone
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
zones
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
## lookup first try by league+season
|
|
141
|
-
league_code = league.to_s.downcase
|
|
142
|
-
season = Season( season )
|
|
143
|
-
|
|
144
|
-
## e.g. world+2022, etc.
|
|
145
|
-
key = "#{league_code}+#{season}"
|
|
146
|
-
zone = @zones[key]
|
|
147
|
-
|
|
148
|
-
## try league e.g. eng.1 etc.
|
|
149
|
-
zone = @zones[league_code] if zone.nil?
|
|
150
|
-
|
|
151
|
-
## try first code only (country code )
|
|
152
|
-
if zone.nil?
|
|
153
|
-
code, _ = league_code.split( '.', 2 )
|
|
154
|
-
zone = @zones[code]
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
if zone.nil? ## still not found; report error
|
|
158
|
-
puts "!! ERROR: no timezone found for #{league} #{season}"
|
|
159
|
-
exit 1
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
zone
|
|
13
|
+
### note - make find_zone! public/global by default - why? why not?
|
|
14
|
+
module Kernel
|
|
15
|
+
include TimezoneHelper
|
|
163
16
|
end
|
|
164
|
-
end # module TimezoneHelper
|
|
165
17
|
|
|
166
18
|
|
|
167
19
|
|
|
20
|
+
require_relative 'football-timezones/datasets'
|
|
21
|
+
|
|
22
|
+
###
|
|
23
|
+
### note - make read_datasets & friends public/global by default - why? why not?
|
|
24
|
+
def read_datasets( path ) Datasets.read( path ); end
|
|
25
|
+
def parse_datasets( str ) Datasets.parse( str ); end
|
|
26
|
+
def parse_datasets_args( args ) Datasets.parse_args( args ); end
|
|
168
27
|
|
|
169
|
-
####
|
|
170
|
-
### note - make find_zone! public/global by default - why? why not?
|
|
171
|
-
module Kernel
|
|
172
|
-
include TimezoneHelper
|
|
173
|
-
end
|
|
174
28
|
|
|
175
29
|
|
|
176
30
|
puts SportDb::Module::Timezones.banner ## say hello
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: football-timezones
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gerald Bauer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-09-
|
|
11
|
+
date: 2024-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: tzinfo
|
|
@@ -107,6 +107,8 @@ files:
|
|
|
107
107
|
- config/timezones_pacific.csv
|
|
108
108
|
- config/timezones_world.csv
|
|
109
109
|
- lib/football-timezones.rb
|
|
110
|
+
- lib/football-timezones/datasets.rb
|
|
111
|
+
- lib/football-timezones/timezones.rb
|
|
110
112
|
- lib/football-timezones/version.rb
|
|
111
113
|
- lib/football/timezones.rb
|
|
112
114
|
homepage: https://github.com/sportdb/sport.db
|