fmrest 0.9.0 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f96cf4500b2417bde1c853954dee03a362088adac933fc7d803d8e37e91cc8a
4
- data.tar.gz: e6cd271dbfef1c87c04a515b8a22e7ead87ec88ab915b37245d4dcecc7c9a237
3
+ metadata.gz: 53c6e0d0260a3b825c031831136651a5f2252d8d0cebd8e2077919caf13d0fb6
4
+ data.tar.gz: 215b6d2a7735ce0a3109ae542f400aa0bee0d60f8808225fc4d77c52009c37d3
5
5
  SHA512:
6
- metadata.gz: 68c4083e32e942fd609b050c2001d32b97c18d88ab70301f10ff0ce31527af2c5faff6e210afceaf152280dc2e0924a8edf2e2994e28ad331d2f015860f172f3
7
- data.tar.gz: 9af1f38e2a59bda96639d6b6f1d3756b007a8c327392159f6288f2365161a94a211ff483744499771716e8e1d61cd8a57876fbfffcf7646e61db52d1794ab1a3
6
+ metadata.gz: 4fdbb4dbc83ed0409e6680e8ffd028794ac01c07335ca43c95bd076e99359c17151b14634cb1a77bd41043ad104566ad5f820805de73d1f683aa957b02ad4fa5
7
+ data.tar.gz: 15966e4cc59a6bb9161f6edd6250beaa948d1c5c69ff911b3f2ca1eba2f782d79b8097c2038513e3ad4b84263b6b9e5f812cc7c37708a72f8a52d8db454b078f
@@ -1,5 +1,13 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.10.0
4
+
5
+ * Added `FmRest::StringDateAwareness` module to correct some issues when using
6
+ `FmRest::StringDate`
7
+ * Added basic timezones support
8
+ * Deprecated `class < FmRest::Spyke::Base(config_hash)` syntax in favor of
9
+ using `self.fmrest_config=`
10
+
3
11
  ### 0.9.0
4
12
 
5
13
  * Added `FmRest::Spyke::Base.set_globals`
data/README.md CHANGED
@@ -120,6 +120,7 @@ Option | Description | Format
120
120
  `:date_format` | Date parsing format | String (FM date format) | `"MM/dd/yyyy"`
121
121
  `:timestamp_format` | Timestmap parsing format | String (FM date format) | `"MM/dd/yyyy HH:mm:ss"`
122
122
  `:time_format` | Time parsing format | String (FM date format) | `"HH:mm:ss"`
123
+ `:timezone` | The timezone for the FM server | `:local` \| `:utc` \: `nil` | `nil`
123
124
 
124
125
  ### Default connection settings
125
126
 
@@ -270,9 +271,9 @@ a DSL in model classes).
270
271
  ### Hybrid string/date objects
271
272
 
272
273
  `FmRest::StringDate` and `FmRest::StringDateTime` are special classes that
273
- inherit from `String`, but internally parse and store a `Date`/`DateTime`
274
- (respectively), and delegate any methods not provided by `String` to those
275
- objects. In other words, they quack like a duck *and* bark like a dog.
274
+ inherit from `String`, but internally parse and store a `Date` or `DateTime`,
275
+ and delegate any methods not provided by `String` to those objects. In other
276
+ words, they quack like a duck *and* bark like a dog.
276
277
 
277
278
  You can use these when you want fmrest-ruby to provide you with date objects,
278
279
  but you don't want to worry about date coercion of false positives (i.e. a
@@ -280,7 +281,29 @@ string field that gets converted to `Date` because it just so matched the given
280
281
  date format).
281
282
 
282
283
  Be warned however that these classes come with a fair share of known gotchas
283
- (see GitHub wiki for more info).
284
+ (see GitHub wiki for more info). Some of those gothas can be removed by calling
285
+
286
+ ```ruby
287
+ FmRest::StringDateAwareness.enable
288
+ ```
289
+
290
+ Which will extend the core `Date` and `DateTime` classes to be aware of
291
+ `FmRest::StringDate`, especially when calling `Date.===`, `Date.parse` or
292
+ `Date._parse`.
293
+
294
+ If you're working with ActiveRecord models this will also make them accept
295
+ `FmRest::StringDate` values for date fields.
296
+
297
+ ### Timezones
298
+
299
+ fmrest-ruby has basic timezone support. You can set the `:timezone` option in
300
+ your connection settings to one of the following values:
301
+
302
+ * `:local` - dates will be converted to your system local time offset (as
303
+ defined by `ENV["TZ"]`), or the timezone set by `Time.zone` if you're using
304
+ ActiveSupport
305
+ * `:utc` - dates will be converted to UTC offset
306
+ * `nil` - (default) ignore timezones altogether
284
307
 
285
308
 
286
309
  ## Spyke support (ActiveRecord-like ORM)
@@ -322,17 +345,6 @@ class Honeybee < FmRest::Spyke::Base
322
345
  end
323
346
  ```
324
347
 
325
- In this case you can pass the [`fmrest_config`](#modelfmrest_config) hash as an
326
- argument to `Base()`:
327
-
328
- ```ruby
329
- class Honeybee < FmRest::Spyke::Base(host: "...", database: "...", username: "...", password: "...")
330
- end
331
-
332
- Honeybee.fmrest_config
333
- # => { host: "...", database: "...", username: "...", password: "..." }
334
- ```
335
-
336
348
  All of Spyke's basic ORM operations work:
337
349
 
338
350
  ```ruby
@@ -8,6 +8,8 @@ module FmRest
8
8
 
9
9
  class << self
10
10
  def Base(config = nil)
11
+ warn "[DEPRECATION] Inheriting from `FmRest::Spyke::Base(config)` is deprecated and will be removed, inherit from `FmRest::Spyke::Base` (without arguments) and use `fmrest_config=` instead"
12
+
11
13
  if config
12
14
  return Class.new(::FmRest::Spyke::Base) do
13
15
  self.fmrest_config = config
@@ -4,10 +4,19 @@ module FmRest
4
4
  module Spyke
5
5
  module Model
6
6
  module Connection
7
- extend ::ActiveSupport::Concern
7
+ extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- class_attribute :fmrest_config, instance_accessor: false, instance_predicate: false
10
+ class_attribute :fmrest_config, instance_writer: false, instance_predicate: false
11
+
12
+ # Overrides the fmrest_config reader created by class_attribute so we
13
+ # can default set the default at call time.
14
+ #
15
+ # This method gets overwriten in subclasses if self.fmrest_config= is
16
+ # called.
17
+ define_singleton_method(:fmrest_config) do
18
+ FmRest.default_connection_settings
19
+ end
11
20
 
12
21
  class_attribute :faraday_block, instance_accessor: false, instance_predicate: false
13
22
  class << self; private :faraday_block, :faraday_block=; end
@@ -40,7 +49,7 @@ module FmRest
40
49
  def fmrest_connection
41
50
  @fmrest_connection ||=
42
51
  begin
43
- config = fmrest_config || FmRest.default_connection_settings
52
+ config = fmrest_config
44
53
 
45
54
  FmRest::V1.build_connection(config) do |conn|
46
55
  faraday_block.call(conn) if faraday_block
@@ -4,8 +4,8 @@ module FmRest
4
4
  module Spyke
5
5
  module Model
6
6
  module Serialization
7
- FM_DATE_FORMAT = "%m/%d/%Y".freeze
8
- FM_DATETIME_FORMAT = "#{FM_DATE_FORMAT} %H:%M:%S".freeze
7
+ FM_DATE_FORMAT = "%m/%d/%Y"
8
+ FM_DATETIME_FORMAT = "#{FM_DATE_FORMAT} %H:%M:%S"
9
9
 
10
10
  # Override Spyke's to_params to return FM Data API's expected JSON
11
11
  # format, and including only modified fields
@@ -63,9 +63,9 @@ module FmRest
63
63
  def serialize_values!(params)
64
64
  params.transform_values! do |value|
65
65
  case value
66
- when DateTime, Time
67
- value.strftime(FM_DATETIME_FORMAT)
68
- when Date
66
+ when DateTime, Time, FmRest::StringDateTime
67
+ convert_datetime_timezone(value.to_datetime).strftime(FM_DATETIME_FORMAT)
68
+ when Date, FmRest::StringDate
69
69
  value.strftime(FM_DATE_FORMAT)
70
70
  else
71
71
  value
@@ -74,6 +74,17 @@ module FmRest
74
74
 
75
75
  params
76
76
  end
77
+
78
+ def convert_datetime_timezone(dt)
79
+ case fmrest_config.fetch(:timezone, nil)
80
+ when :utc, "utc"
81
+ dt.new_offset(0)
82
+ when :local, "local"
83
+ dt.new_offset(FmRest::V1.local_offset_for_datetime(dt))
84
+ when nil
85
+ dt
86
+ end
87
+ end
77
88
  end
78
89
  end
79
90
  end
@@ -79,17 +79,24 @@ module FmRest
79
79
  class InvalidDate < ArgumentError; end
80
80
 
81
81
  class << self
82
- alias_method :strptime, :new
82
+ def strptime(str, date_format, *_)
83
+ begin
84
+ date = self::DELEGATE_CLASS.strptime(str, date_format)
85
+ rescue ArgumentError
86
+ raise InvalidDate
87
+ end
88
+
89
+ new(str, date)
90
+ end
83
91
  end
84
92
 
85
- def initialize(str, date_format, **str_args)
93
+ def initialize(str, date, **str_args)
94
+ raise ArgumentError, "str must be of class String" unless str.is_a?(String)
95
+ raise ArgumentError, "date must be of class #{self.class::DELEGATE_CLASS.name}" unless date.is_a?(self.class::DELEGATE_CLASS)
96
+
86
97
  super(str, **str_args)
87
98
 
88
- begin
89
- @delegate = self.class::DELEGATE_CLASS.strptime(str, date_format)
90
- rescue ArgumentError
91
- raise InvalidDate
92
- end
99
+ @delegate = date
93
100
 
94
101
  freeze
95
102
  end
@@ -178,4 +185,36 @@ module FmRest
178
185
  @delegate
179
186
  end
180
187
  end
188
+
189
+ module StringDateAwareness
190
+ def _parse(v, *_)
191
+ if v.is_a?(StringDateTime)
192
+ return { year: v.year, mon: v.month, mday: v.mday, hour: v.hour, min: v.min, sec: v.sec, sec_fraction: v.sec_fraction, offset: v.offset }
193
+ end
194
+ if v.is_a?(StringDate)
195
+ return { year: v.year, mon: v.month, mday: v.mday }
196
+ end
197
+ super
198
+ end
199
+
200
+ def parse(v, *_)
201
+ if v.is_a?(StringDate)
202
+ return self == ::DateTime ? v.to_datetime : v.to_date
203
+ end
204
+ super
205
+ end
206
+
207
+ # Overriding case equality method so that it returns true for
208
+ # `FmRest::StringDate` instances
209
+ #
210
+ # Calls superclass method
211
+ #
212
+ def ===(other)
213
+ super || other.is_a?(StringDate)
214
+ end
215
+
216
+ def self.enable(classes: [Date, DateTime])
217
+ classes.each { |klass| klass.singleton_class.prepend(self) }
218
+ end
219
+ end
181
220
  end
@@ -4,6 +4,7 @@ require "fmrest/v1/connection"
4
4
  require "fmrest/v1/paths"
5
5
  require "fmrest/v1/container_fields"
6
6
  require "fmrest/v1/utils"
7
+ require "fmrest/v1/dates"
7
8
 
8
9
  module FmRest
9
10
  module V1
@@ -15,5 +16,6 @@ module FmRest
15
16
  extend Paths
16
17
  extend ContainerFields
17
18
  extend Utils
19
+ extend Dates
18
20
  end
19
21
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FmRest
4
+ module V1
5
+ module Dates
6
+ FM_DATETIME_FORMAT_MATCHER = /MM|mm|dd|HH|ss|yyyy/.freeze
7
+
8
+ FM_DATE_TO_STRPTIME_SUBSTITUTIONS = {
9
+ "MM" => "%m",
10
+ "dd" => "%d",
11
+ "yyyy" => "%Y",
12
+ "HH" => "%H",
13
+ "mm" => "%M",
14
+ "ss" => "%S"
15
+ }.freeze
16
+
17
+ FM_DATE_TO_REGEXP_SUBSTITUTIONS = {
18
+ "MM" => '(?:0[1-9]|1[012])',
19
+ "dd" => '(?:0[1-9]|[12][0-9]|3[01])',
20
+ "yyyy" => '\d{4}',
21
+ "HH" => '(?:[01]\d|2[0123])',
22
+ "mm" => '[0-5]\d',
23
+ "ss" => '[0-5]\d'
24
+ }.freeze
25
+
26
+ def self.extended(mod)
27
+ mod.instance_eval do
28
+ @date_strptime = {}
29
+ @date_regexp = {}
30
+ end
31
+ end
32
+
33
+ # Converts a FM date-time format to `DateTime.strptime` format
34
+ #
35
+ # @param fm_format [String] The FileMaker date-time format
36
+ # @return [String] The `DateTime.strpdate` equivalent of the given FM
37
+ # date-time format
38
+ def fm_date_to_strptime_format(fm_format)
39
+ @date_strptime[fm_format] ||=
40
+ fm_format.gsub(FM_DATETIME_FORMAT_MATCHER, FM_DATE_TO_STRPTIME_SUBSTITUTIONS).freeze
41
+ end
42
+
43
+ # Converts a FM date-time format to a Regexp. This is mostly used a
44
+ # quicker way of checking whether a FM field is a date field than
45
+ # Date|DateTime.strptime
46
+ #
47
+ # @param fm_format [String] The FileMaker date-time format
48
+ # @return [Regexp] A reegular expression matching strings in the given FM
49
+ # date-time format
50
+ def fm_date_to_regexp(fm_format)
51
+ @date_regexp[fm_format] ||=
52
+ Regexp.new('\A' + fm_format.gsub(FM_DATETIME_FORMAT_MATCHER, FM_DATE_TO_REGEXP_SUBSTITUTIONS) + '\Z').freeze
53
+ end
54
+
55
+ # Takes a DateTime dt, and returns the correct local offset for that dt,
56
+ # daylight savings included, in fraction of a day.
57
+ #
58
+ # By default, if ActiveSupport's Time.zone is set it will be used instead
59
+ # of the system timezone.
60
+ #
61
+ # @param dt [DateTime] The DateTime to get the offset for
62
+ # @param zone [nil, String, TimeZone] The timezone to use to calculate
63
+ # the offset (defaults to system timezone, or ActiveSupport's Time.zone
64
+ # if set)
65
+ # @return [Rational] The offset in fraction of a day
66
+ def local_offset_for_datetime(dt, zone = nil)
67
+ dt = dt.new_offset(0)
68
+ time = ::Time.utc(dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec)
69
+
70
+ # Do we have ActiveSupport's TimeZone?
71
+ time = if time.respond_to?(:in_time_zone)
72
+ time.in_time_zone(zone || ::Time.zone)
73
+ else
74
+ time.localtime
75
+ end
76
+
77
+ Rational(time.utc_offset, 86400) # seconds in one day (24*60*60)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -5,7 +5,8 @@ require "fmrest/string_date"
5
5
  module FmRest
6
6
  module V1
7
7
  class TypeCoercer < Faraday::Response::Middleware
8
- # We use this date to represent a time for consistency with ginjo-rfm
8
+ # We use this date to represent a FileMaker time for consistency with
9
+ # ginjo-rfm
9
10
  JULIAN_ZERO_DAY = "-4712/1/1"
10
11
 
11
12
  COERCE_HYBRID = [:hybrid, "hybrid", true].freeze
@@ -30,15 +31,13 @@ module FmRest
30
31
  field_data = record["fieldData"] || record[:fieldData]
31
32
  portal_data = record["portalData"] || record[:portalData]
32
33
 
33
- # Build an enumerator that iterates over hashes of fields
34
- enum = Enumerator.new { |y| y << field_data }
35
- if portal_data
36
- portal_data.each_value do |portal_records|
37
- enum += portal_records.to_enum
34
+ coerce_fields(field_data)
35
+
36
+ portal_data.try(:each_value) do |portal_records|
37
+ portal_records.each do |pr|
38
+ coerce_fields(pr)
38
39
  end
39
40
  end
40
-
41
- enum.each { |hash| coerce_fields(hash) }
42
41
  end
43
42
  end
44
43
 
@@ -49,29 +48,49 @@ module FmRest
49
48
  next unless v.is_a?(String)
50
49
  next if k == "recordId" || k == :recordId || k == "modId" || k == :modId
51
50
 
52
- begin
53
- str_timestamp = datetime_class.strptime(v, datetime_format)
54
- hash[k] = str_timestamp
55
- next
56
- rescue ArgumentError
51
+ if quick_check_timestamp(v)
52
+ begin
53
+ hash[k] = coerce_timestamp(v)
54
+ next
55
+ rescue ArgumentError
56
+ end
57
57
  end
58
58
 
59
- begin
60
- str_date = date_class.strptime(v, date_format)
61
- hash[k] = str_date
62
- next
63
- rescue ArgumentError
59
+ if quick_check_date(v)
60
+ begin
61
+ hash[k] = date_class.strptime(v, date_strptime_format)
62
+ next
63
+ rescue ArgumentError
64
+ end
64
65
  end
65
66
 
66
- begin
67
- str_time = datetime_class.strptime("#{JULIAN_ZERO_DAY} #{v}", time_format)
68
- hash[k] = str_time
69
- next
70
- rescue ArgumentError
67
+ if quick_check_time(v)
68
+ begin
69
+ hash[k] = datetime_class.strptime("#{JULIAN_ZERO_DAY} #{v}", time_strptime_format)
70
+ next
71
+ rescue ArgumentError
72
+ end
71
73
  end
72
74
  end
73
75
  end
74
76
 
77
+ def coerce_timestamp(str)
78
+ str_timestamp = DateTime.strptime(str, datetime_strptime_format)
79
+
80
+ if local_timezone?
81
+ # Change the DateTime to the local timezone, keeping the same
82
+ # time and just modifying the timezone
83
+ offset = FmRest::V1.local_offset_for_datetime(str_timestamp)
84
+ str_timestamp = str_timestamp.new_offset(offset) - offset
85
+ end
86
+
87
+ if datetime_class == StringDateTime
88
+ str_timestamp = StringDateTime.new(str, str_timestamp)
89
+ end
90
+
91
+ str_timestamp
92
+ end
93
+
75
94
  def date_class
76
95
  @date_class ||=
77
96
  case coerce_dates
@@ -92,19 +111,75 @@ module FmRest
92
111
  end
93
112
  end
94
113
 
95
- def date_format
96
- @date_format ||=
97
- FmRest::V1.convert_date_time_format(@options[:date_format] || DEFAULT_DATE_FORMAT)
114
+ def date_fm_format
115
+ @options[:date_format] || DEFAULT_DATE_FORMAT
116
+ end
117
+
118
+ def timestamp_fm_format
119
+ @options[:timestamp_format] || DEFAULT_TIMESTAMP_FORMAT
120
+ end
121
+
122
+ def time_fm_format
123
+ @options[:time_format] || DEFAULT_TIME_FORMAT
98
124
  end
99
125
 
100
- def datetime_format
101
- @datetime_format ||=
102
- FmRest::V1.convert_date_time_format(@options[:timestamp_format] || DEFAULT_TIMESTAMP_FORMAT)
126
+ def date_strptime_format
127
+ FmRest::V1.fm_date_to_strptime_format(date_fm_format)
128
+ end
129
+
130
+ def datetime_strptime_format
131
+ FmRest::V1.fm_date_to_strptime_format(timestamp_fm_format)
132
+ end
133
+
134
+ def time_strptime_format
135
+ @time_strptime_format ||=
136
+ "%Y/%m/%d " + FmRest::V1.fm_date_to_strptime_format(time_fm_format)
137
+ end
138
+
139
+ # We use a string length test, followed by regexp match test to try to
140
+ # identify date fields. Benchmarking shows this should be between 1 and 3
141
+ # orders of magnitude faster for fails (i.e. non-dates) than just using
142
+ # Date.strptime.
143
+ #
144
+ # user system total real
145
+ # strptime: 0.268496 0.000962 0.269458 ( 0.270865)
146
+ # re=~: 0.024872 0.000070 0.024942 ( 0.025057)
147
+ # re.match?: 0.019745 0.000095 0.019840 ( 0.020058)
148
+ # strptime fail: 0.141309 0.000354 0.141663 ( 0.142266)
149
+ # re=~ fail: 0.031637 0.000095 0.031732 ( 0.031872)
150
+ # re.match? fail: 0.011249 0.000056 0.011305 ( 0.011375)
151
+ # length fail: 0.007177 0.000024 0.007201 ( 0.007222)
152
+ #
153
+ # NOTE: The faster Regexp#match? was introduced in Ruby 2.4.0, so we
154
+ # can't really rely on it being available
155
+ if //.respond_to?(:match?)
156
+ def quick_check_timestamp(v)
157
+ v.length == timestamp_fm_format.length && FmRest::V1::fm_date_to_regexp(timestamp_fm_format).match?(v)
158
+ end
159
+
160
+ def quick_check_date(v)
161
+ v.length == date_fm_format.length && FmRest::V1::fm_date_to_regexp(date_fm_format).match?(v)
162
+ end
163
+
164
+ def quick_check_time(v)
165
+ v.length == time_fm_format.length && FmRest::V1::fm_date_to_regexp(time_fm_format).match?(v)
166
+ end
167
+ else
168
+ def quick_check_timestamp(v)
169
+ v.length == timestamp_fm_format.length && FmRest::V1::fm_date_to_regexp(timestamp_fm_format) =~ v
170
+ end
171
+
172
+ def quick_check_date(v)
173
+ v.length == date_fm_format.length && FmRest::V1::fm_date_to_regexp(date_fm_format) =~ v
174
+ end
175
+
176
+ def quick_check_time(v)
177
+ v.length == time_fm_format.length && FmRest::V1::fm_date_to_regexp(time_fm_format) =~ v
178
+ end
103
179
  end
104
180
 
105
- def time_format
106
- @time_format ||=
107
- "%Y/%m/%d " + FmRest::V1.convert_date_time_format(@options[:time_format] || DEFAULT_TIME_FORMAT)
181
+ def local_timezone?
182
+ @local_timezone ||= @options.fetch(:timezone, nil).try(:to_sym) == :local
108
183
  end
109
184
 
110
185
  def coerce_dates
@@ -5,17 +5,6 @@ module FmRest
5
5
  module Utils
6
6
  VALID_SCRIPT_KEYS = [:prerequest, :presort, :after].freeze
7
7
 
8
- FM_DATETIME_FORMAT_MATCHER = /MM|mm|dd|HH|ss|yyyy/.freeze
9
-
10
- FM_DATETIME_FORMAT_SUBSTITUTIONS = {
11
- "MM" => "%m",
12
- "dd" => "%d",
13
- "yyyy" => "%Y",
14
- "HH" => "%H",
15
- "mm" => "%M",
16
- "ss" => "%S"
17
- }.freeze
18
-
19
8
  # Converts custom script options to a hash with the Data API's expected
20
9
  # JSON script format.
21
10
  #
@@ -83,11 +72,6 @@ module FmRest
83
72
  params
84
73
  end
85
74
 
86
- # Converts a FM date-time format to `Date.strptime` format
87
- #
88
- def convert_date_time_format(fm_format)
89
- fm_format.gsub(FM_DATETIME_FORMAT_MATCHER, FM_DATETIME_FORMAT_SUBSTITUTIONS)
90
- end
91
75
 
92
76
  private
93
77
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FmRest
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fmrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Carbajal
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-17 00:00:00.000000000 Z
11
+ date: 2020-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -266,6 +266,7 @@ files:
266
266
  - lib/fmrest/v1.rb
267
267
  - lib/fmrest/v1/connection.rb
268
268
  - lib/fmrest/v1/container_fields.rb
269
+ - lib/fmrest/v1/dates.rb
269
270
  - lib/fmrest/v1/paths.rb
270
271
  - lib/fmrest/v1/raise_errors.rb
271
272
  - lib/fmrest/v1/token_session.rb