timeliness 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22c5b15397d7f945442d9768efb71ebbb243e7d44b8948d8ccf03e31c70858b3
4
- data.tar.gz: 96ac6e12fd20b0b5530e3ae99e60b2df81c9014bd7cedba26fa6e9395268d8b5
3
+ metadata.gz: 830b2a8f549031529ac5f153c60e80c4f6babae4edfd5e883fc954645f350322
4
+ data.tar.gz: 74ed311a9aa4a2da4d995a774e1ee438ee1454708cb25d991dfac30440d4cdcc
5
5
  SHA512:
6
- metadata.gz: d3c968646a9f6bc9d867d31c062724e162c8824fd4feb9f76a682f46cfd20cf817948b06bb1f14731eb2f3bb2be5d433edcb39d51ee8655e863898940f9ebf08
7
- data.tar.gz: 5eb2af292e5248ee58cfd539bad3491c668adf8c564579c1694ebffd0163e27d0353aec2bd0d478923d930d796d878ca8e99861ea15c9ea86d4bac9089ce16f8
6
+ metadata.gz: 66516e7c7cd33f1ef1c030f99a9e0ede74a39091c18d8c039310894a4e9ef7069c3630ac9bb6e2fe2f2b9be1acd68ca17e0036645842f56a489101776417264c
7
+ data.tar.gz: a1334464ba03f8c55245ab93ea8d26267900e5af3c2a6b6340d566e7cf59917758526ac2ab9165424568c84a8058932129fecc9a1caa844d2cb067bc0a679fdb
@@ -1,3 +1,8 @@
1
+ = 0.4.2 - 2019-06-15
2
+ * Fixed thread safe issue that forced you to use one of the date format methods e.g. `use_euro_formats`
3
+ to initialize the format sets in each new thread. Now a new thread will default to the global default (main thread).
4
+ * Add `Timeliness.ambiguous_date_format` config setting (:us or :euro) to control global default for date format sets.
5
+
1
6
  = 0.4.1 - 2019-06-11
2
7
  * Add format for ISO 8601 with usec and 'Z' UTC zone offset (jartek)
3
8
  * Fix ISO 8601 parsing bug where Z was not recognised as UTC
@@ -236,7 +236,7 @@ To see all defined formats look at the {source code}[http://github.com/adzap/tim
236
236
  === US/Euro Formats
237
237
 
238
238
  The perennial problem for non-US developers or applications not primarily for the US, is the US date
239
- format of m/d/yy. This is ambiguous with the European format of d/m/yy. By default the gem uses the
239
+ format of m/d/yy. This is can be ambiguous with the European format of d/m/yy. By default the gem uses the
240
240
  US formats as this is the Ruby default
241
241
  when it does date interpretation.
242
242
 
@@ -250,6 +250,13 @@ You can switch back to US formats with
250
250
 
251
251
  Timeliness.use_us_formats
252
252
 
253
+ ==== Thread Safety
254
+
255
+ The switching of formats is threadsafe (since v0.4.0), however for each new thread the format default will be
256
+ the gem default, being the US format. To control default for your app and each new thread, use the config
257
+
258
+ Timeliness.ambiguous_date_format = :euro
259
+
253
260
 
254
261
  === Customising Formats
255
262
 
@@ -2,7 +2,6 @@ require 'date'
2
2
  require 'forwardable'
3
3
 
4
4
  require 'timeliness/helpers'
5
- require 'timeliness/threadsafe_attr'
6
5
  require 'timeliness/definitions'
7
6
  require 'timeliness/format'
8
7
  require 'timeliness/format_set'
@@ -14,7 +13,7 @@ module Timeliness
14
13
  extend Forwardable
15
14
  def_delegators Parser, :parse, :_parse
16
15
  def_delegators Definitions, :add_formats, :remove_formats, :use_us_formats, :use_euro_formats
17
- attr_accessor :default_timezone, :date_for_time_type, :ambiguous_year_threshold
16
+ attr_accessor :default_timezone, :date_for_time_type, :ambiguous_date_format, :ambiguous_year_threshold
18
17
  end
19
18
 
20
19
  # Default timezone. Options:
@@ -31,6 +30,12 @@ module Timeliness
31
30
  #
32
31
  self.date_for_time_type = lambda { Time.now }
33
32
 
33
+ # Default parsing of ambiguous date formats. Options:
34
+ # - :us (default, 01/02/2000 = 2nd of January 2000)
35
+ # - :euro (01/02/2000 = 1st of February 2000)
36
+ #
37
+ self.ambiguous_date_format = :us
38
+
34
39
  # Set the threshold value for a two digit year to be considered last century
35
40
  #
36
41
  # Default: 30
@@ -155,9 +155,8 @@ module Timeliness
155
155
  DuplicateFormat = Class.new(StandardError)
156
156
 
157
157
  class << self
158
- extend ThreadsafeAttr
159
158
  attr_accessor :time_formats, :date_formats, :datetime_formats, :format_tokens, :format_components, :timezone_mapping
160
- threadsafe_attr_accessor :date_format_set, :time_format_set, :datetime_format_set
159
+ attr_reader :time_format_set, :date_format_set, :datetime_format_set
161
160
 
162
161
  # Adds new formats. Must specify format type and can specify a :before
163
162
  # option to nominate which format the new formats should be inserted in
@@ -191,35 +190,51 @@ module Timeliness
191
190
  compile_formats
192
191
  end
193
192
 
194
- # Removes US date formats so that ambiguous dates are parsed as European format
193
+ def current_date_format=(value)
194
+ Thread.current["Timeliness.current_date_format"] = value
195
+ end
196
+
197
+ def current_date_format
198
+ Thread.current["Timeliness.current_date_format"] ||= @current_date_format
199
+ end
200
+
201
+ # Get date format set for using current thread format setting
202
+ def date_format_set
203
+ instance_variable_get(:"@#{current_date_format}_date_format_set")
204
+ end
205
+
206
+ # Get datetime format set for using current thread format setting
207
+ def datetime_format_set
208
+ instance_variable_get(:"@#{current_date_format}_datetime_format_set")
209
+ end
210
+
211
+ # Use date formats that return ambiguous dates parsed in European format
195
212
  #
196
213
  def use_euro_formats
197
- self.date_format_set = @euro_date_format_set
198
- self.datetime_format_set = @euro_datetime_format_set
214
+ self.current_date_format = :euro
199
215
  end
200
216
 
201
- # Restores default to parse ambiguous dates as US format
217
+ # Use date formats that return ambiguous dates parsed as US format
202
218
  #
203
219
  def use_us_formats
204
- self.date_format_set = @us_date_format_set
205
- self.datetime_format_set = @us_datetime_format_set
220
+ self.current_date_format = :us
206
221
  end
207
222
 
208
223
  def compile_formats
209
- @sorted_token_keys = nil
210
- self.time_format_set = FormatSet.compile(time_formats)
224
+ @sorted_token_keys = nil
225
+ @current_date_format = Timeliness.ambiguous_date_format
211
226
 
227
+ self.current_date_format = @current_date_format
228
+
229
+ @time_format_set = FormatSet.compile(time_formats)
212
230
  @us_date_format_set = FormatSet.compile(date_formats)
213
231
  @us_datetime_format_set = FormatSet.compile(datetime_formats)
214
232
  @euro_date_format_set = FormatSet.compile(date_formats.select { |format| US_FORMAT_REGEXP !~ format })
215
233
  @euro_datetime_format_set = FormatSet.compile(datetime_formats.select { |format| US_FORMAT_REGEXP !~ format })
216
-
217
- self.date_format_set = @us_date_format_set
218
- self.datetime_format_set = @us_datetime_format_set
219
234
  end
220
235
 
221
236
  def sorted_token_keys
222
- @sorted_token_keys ||= format_tokens.keys.sort {|a,b| a.size <=> b.size }.reverse
237
+ @sorted_token_keys ||= format_tokens.keys.sort_by(&:size).reverse
223
238
  end
224
239
 
225
240
  # Returns format for type and other possible matching format set based on type
@@ -1,3 +1,3 @@
1
1
  module Timeliness
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  end
@@ -102,15 +102,25 @@ describe Timeliness::Definitions do
102
102
  end
103
103
  end
104
104
 
105
- context "threadsafety" do
106
- it "should allow threadsafe use of regional formats" do
107
- eu_date = "30/06/2016"
108
- us_date = "06/30/2016"
109
- threads = []
110
- threads << Thread.new { Timeliness.use_euro_formats; sleep(0.005); Timeliness.parse(eu_date) }
111
- threads << Thread.new { sleep(0.001); Timeliness.use_us_formats; Timeliness.parse(us_date) }
112
- threads.each { |t| t.join }
113
- threads.each { |t| expect(t.value).to eql(Time.new(2016,06,30)) }
105
+ context "thread safe date format switching" do
106
+ let(:ambiguous_date) { "01/02/2000" }
107
+
108
+ it "should allow indepdent regional format control in current thread" do
109
+ threads = {
110
+ euro: Thread.new { Timeliness.use_euro_formats; sleep(0.005); Timeliness.parse(ambiguous_date) },
111
+ us: Thread.new { sleep(0.001); Timeliness.use_us_formats; Timeliness.parse(ambiguous_date) }
112
+ }
113
+ threads.values.each { |t| t.join }
114
+
115
+ expect(threads[:euro].value).to eql(Time.new(2000,2,1))
116
+ expect(threads[:us].value).to eql(Time.new(2000,1,2))
117
+ end
118
+
119
+ it 'should use default regional format in new threads' do
120
+ thread = Thread.new { sleep(0.001); Timeliness.parse(ambiguous_date) }
121
+ thread.join
122
+
123
+ expect(thread.value).to eql(Time.new(2000,1,2))
114
124
  end
115
125
  end
116
126
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeliness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Meehan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-11 00:00:00.000000000 Z
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -102,7 +102,6 @@ files:
102
102
  - lib/timeliness/format_set.rb
103
103
  - lib/timeliness/helpers.rb
104
104
  - lib/timeliness/parser.rb
105
- - lib/timeliness/threadsafe_attr.rb
106
105
  - lib/timeliness/version.rb
107
106
  - spec/spec_helper.rb
108
107
  - spec/timeliness/core_ext/string_spec.rb
@@ -1,24 +0,0 @@
1
- module Timeliness
2
- module ThreadsafeAttr
3
- def threadsafe_attr_accessor(*attrs)
4
- attrs.each do |attr|
5
- storage_name = "#{name}.#{attr}".freeze
6
- reader attr, storage_name
7
- writer attr, storage_name
8
- end
9
- end
10
-
11
- private
12
- def reader(attr, storage_name)
13
- define_method(attr) do
14
- Thread.current[storage_name]
15
- end
16
- end
17
-
18
- def writer(attr, storage_name)
19
- define_method("#{attr}=") do |value|
20
- Thread.current[storage_name] = value
21
- end
22
- end
23
- end
24
- end