sheets_v4 0.6.0 → 0.7.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 +11 -0
- data/README.md +65 -1
- data/examples/README.md +1 -0
- data/lib/sheets_v4/{validate_api_objects → api_object_validation}/load_schemas.rb +7 -7
- data/lib/sheets_v4/{validate_api_objects → api_object_validation}/resolve_schema_ref.rb +6 -6
- data/lib/sheets_v4/{validate_api_objects → api_object_validation}/traverse_object_tree.rb +2 -2
- data/lib/sheets_v4/api_object_validation/validate_api_object.rb +87 -0
- data/lib/sheets_v4/api_object_validation.rb +20 -0
- data/lib/sheets_v4/color.rb +0 -1
- data/lib/sheets_v4/convert_dates_and_times.rb +243 -0
- data/lib/sheets_v4/{credential_creator.rb → create_credential.rb} +2 -2
- data/lib/sheets_v4/validate_api_objects/{validate.rb → validate_api_object.rb} +7 -6
- data/lib/sheets_v4/validate_api_objects.rb +6 -6
- data/lib/sheets_v4/version.rb +1 -1
- data/lib/sheets_v4.rb +219 -95
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3ed35f7562643f623e68d6ad41c497f1d92ea7b2d77f4b6f0d5e02586109897
|
4
|
+
data.tar.gz: 6687dfc41d70870694a2085e749d803f7062de8d2486866e4e44ea54b1eec95f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00334f58b9080916f1239671e106292742a00bbd931582577ae8a0664c25ea83f1ecaf5154996a0f28deffe9e8aaf58e4963dd94160095853d7d3454ef9e1b82
|
7
|
+
data.tar.gz: a89714057c1aa145ce2b5eaa5a05776b8593c76d6e944b1b2b868b1ddd16a4247bf05ac13b218b74addb0204a3644cb6657e30e2331e725ca68467359cfd66a9
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,17 @@ Changes for each release are listed in this file.
|
|
4
4
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/) for its releases.
|
6
6
|
|
7
|
+
## v0.7.0 (2023-10-08)
|
8
|
+
|
9
|
+
[Full Changelog](https://github.com/main-branch/sheets_v4/compare/v0.6.0..v0.7.0)
|
10
|
+
|
11
|
+
Changes since v0.6.0:
|
12
|
+
|
13
|
+
* 616fe1f Add conversions bewteen Date/DateTime and spreadsheet values (#22)
|
14
|
+
* 6f37337 Rename SheetsV4::ValidateApiObjects to SheetsV4::ApiObjectValidation (#21)
|
15
|
+
* 0f76992 Rename SheetsV4::ValidateApiObjects::Validate to SheetsV4::ValidateApiObjects::ValidateApiObject (#20)
|
16
|
+
* e80040c Rename SheetsV4::CredentialCreator to SheetsV4::CreateCredential (#19)
|
17
|
+
|
7
18
|
## v0.6.0 (2023-10-03)
|
8
19
|
|
9
20
|
[Full Changelog](https://github.com/main-branch/sheets_v4/compare/v0.5.0..v0.6.0)
|
data/README.md
CHANGED
@@ -25,6 +25,7 @@ Unofficial helpers for the Google Sheets V4 API
|
|
25
25
|
* [Method 2: constructing requests using hashes](#method-2-constructing-requests-using-hashes)
|
26
26
|
* [Which method should be used?](#which-method-should-be-used)
|
27
27
|
* [Validating requests](#validating-requests)
|
28
|
+
* [Working with dates and times](#working-with-dates-and-times)
|
28
29
|
* [Colors](#colors)
|
29
30
|
* [Development](#development)
|
30
31
|
* [Contributing](#contributing)
|
@@ -125,7 +126,7 @@ sheets_service = File.open('credential.json') do |credential_source|
|
|
125
126
|
end
|
126
127
|
```
|
127
128
|
|
128
|
-
or an already constructed `Google::Auth
|
129
|
+
or an already constructed `Google::Auth::*` object.
|
129
130
|
|
130
131
|
### Building a request
|
131
132
|
|
@@ -273,6 +274,69 @@ request:
|
|
273
274
|
SheetsV4.validate_api_object(schema: 'batch_update_spreadsheet_request', object: requests)
|
274
275
|
```
|
275
276
|
|
277
|
+
### Working with dates and times
|
278
|
+
|
279
|
+
Google Sheets, similar to other spreadsheet programs, stores dates and date-time
|
280
|
+
values as numbers. This system makes it easier to perform calculations with
|
281
|
+
dates and times.
|
282
|
+
|
283
|
+
This gem provides two sets of equavalent conversion methods. The first set is defined
|
284
|
+
as class methods on the `SheetsV4` class.
|
285
|
+
|
286
|
+
* `SheetsV4.date_to_gs(date)` returns a numeric cell value
|
287
|
+
* `SheetsV4.gs_to_date(cell_value)` returns a Date object
|
288
|
+
* `SheetsV4.datetime_to_gs(datetime)` returns a numeric cell value
|
289
|
+
* `SheetsV4.gs_to_datetime(cell_value)` returns a DateTime object
|
290
|
+
|
291
|
+
In order to convert to and from spreadsheet values, the spreadsheet timezone must
|
292
|
+
be known. A spreadsheet's timezone is found in the Google Sheets spreadsheet object's
|
293
|
+
properties:
|
294
|
+
|
295
|
+
```Ruby
|
296
|
+
SheetsV4.default_spreadsheet_tz = spreadsheet.properties.time_zone
|
297
|
+
```
|
298
|
+
|
299
|
+
If a time zone is not set using `SheetsV4.default_spreadsheet_tz`, a RuntimeError
|
300
|
+
will be raised when any of the above methods are used.
|
301
|
+
|
302
|
+
Here is an example of how the timezone can change the values fetched from the
|
303
|
+
spreadsheet:
|
304
|
+
|
305
|
+
```Ruby
|
306
|
+
cell_value = 44333.191666666666
|
307
|
+
|
308
|
+
SheetsV4.default_spreadsheet_tz = 'America/New_York'
|
309
|
+
datetime = SheetsV4.gs_to_datetime(cell_value) #=> Mon, 17 May 2021 04:36:00 -0400
|
310
|
+
datetime.utc #=> 2021-05-17 08:36:00 UTC
|
311
|
+
|
312
|
+
SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
313
|
+
datetime = SheetsV4.gs_to_datetime(cell_value) #=> Mon, 17 May 2021 04:36:00 -0700
|
314
|
+
datetime.utc #=> 2021-05-17 11:36:00 UTC
|
315
|
+
```
|
316
|
+
|
317
|
+
Valid time zone names are those listed in one of these two sources:
|
318
|
+
|
319
|
+
* `ActiveSupport::TimeZone.all.map { |tz| tz.tzinfo.name }`
|
320
|
+
* `ActiveSupport::TimeZone.all.map(&:name)`
|
321
|
+
|
322
|
+
The `SheetsV4` methods works well if the spreadsheet timezone is constant through
|
323
|
+
the run of the program. If this is not the case -- for instance when working with
|
324
|
+
multiple spreadsheets whose timezones may be different -- then use
|
325
|
+
`SheetsV4::ConvertDatesAndTimes`.
|
326
|
+
|
327
|
+
Each instance of `SheetsV4::ConvertDatesAndTimes` has it's own spreadsheet timezone
|
328
|
+
used in the conversions. Instance methods for this class are the same as the
|
329
|
+
date conversion methods on the SheetsV4 class.
|
330
|
+
|
331
|
+
Example:
|
332
|
+
|
333
|
+
```Ruby
|
334
|
+
cell_value = 44333.191666666666
|
335
|
+
converter = SheetsV4::ConvertDatesAndTimes.new('America/Los_Angeles')
|
336
|
+
datetime = SheetsV4.gs_to_datetime(cell_value) #=> Mon, 17 May 2021 04:36:00 -0700
|
337
|
+
datetime.utc #=> 2021-05-17 11:36:00 UTC
|
338
|
+
```
|
339
|
+
|
276
340
|
### Colors
|
277
341
|
|
278
342
|
Color objects (with appropriate :red, :green, :blue values) can be retrieved by name
|
data/examples/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SheetsV4
|
4
|
-
module
|
4
|
+
module ApiObjectValidation
|
5
5
|
# Load the Google Discovery API description for the Sheets V4 API
|
6
6
|
#
|
7
7
|
# @example
|
8
8
|
# logger = Logger.new(STDOUT, :level => Logger::ERROR)
|
9
|
-
# schemas = SheetsV4::
|
9
|
+
# schemas = SheetsV4::ApiObjectValidation::LoadSchemas.new(logger:).call
|
10
10
|
#
|
11
11
|
# @api private
|
12
12
|
#
|
@@ -18,7 +18,7 @@ module SheetsV4
|
|
18
18
|
# The schemas are only loaded once and cached.
|
19
19
|
#
|
20
20
|
# @example
|
21
|
-
# schema_loader = SheetsV4::
|
21
|
+
# schema_loader = SheetsV4::ApiObjectValidation::LoadSchemas.new
|
22
22
|
#
|
23
23
|
# @param logger [Logger] the logger to use
|
24
24
|
#
|
@@ -30,8 +30,8 @@ module SheetsV4
|
|
30
30
|
#
|
31
31
|
# @example
|
32
32
|
# logger = Logger.new(STDOUT, :level => Logger::INFO)
|
33
|
-
#
|
34
|
-
#
|
33
|
+
# schema_loader = SheetsV4::ApiObjectValidation::LoadSchemas.new(logger)
|
34
|
+
# schema_loader.logger == logger # => true
|
35
35
|
#
|
36
36
|
# @return [Logger]
|
37
37
|
#
|
@@ -84,7 +84,7 @@ module SheetsV4
|
|
84
84
|
# Log an error and raise a RuntimeError based on the HTTP response code
|
85
85
|
# @param http_response [Net::HTTPResponse] the HTTP response
|
86
86
|
# @return [void]
|
87
|
-
# @
|
87
|
+
# @raise [RuntimeError]
|
88
88
|
# @api private
|
89
89
|
def raise_error(http_response)
|
90
90
|
message = "HTTP Error '#{http_response.code}' loading schemas from '#{http_response.uri}'"
|
@@ -146,7 +146,7 @@ module SheetsV4
|
|
146
146
|
# @return [void]
|
147
147
|
# @api private
|
148
148
|
def post_process_schemas(schemas)
|
149
|
-
SheetsV4::
|
149
|
+
SheetsV4::ApiObjectValidation::TraverseObjectTree.call(
|
150
150
|
object: schemas, visitor: ->(path:, object:) { schema_visitor(path:, object:) }
|
151
151
|
)
|
152
152
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SheetsV4
|
4
|
-
module
|
4
|
+
module ApiObjectValidation
|
5
5
|
# Resolve a JSON schema reference to a Google Sheets API schema
|
6
6
|
#
|
7
7
|
# This class uses the Google Discovery API to get the schemas. Any schema reference
|
@@ -9,14 +9,14 @@ module SheetsV4
|
|
9
9
|
# name in the Google Discovery API and returning the schema object (as a Hash).
|
10
10
|
#
|
11
11
|
# This means that `{ "$ref": "cell_data" }` is resolved by returning
|
12
|
-
# `SheetsV4::
|
12
|
+
# `SheetsV4::ApiObjectValidation::LoadSchemas.new(logger:).call['cell_data']`.
|
13
13
|
#
|
14
|
-
# An RuntimeError is raised if `SheetsV4::
|
14
|
+
# An RuntimeError is raised if `SheetsV4::ApiObjectValidation::LoadSchemas.new.call`
|
15
15
|
# does not have a key matching the schema name.
|
16
16
|
#
|
17
17
|
# @example
|
18
18
|
# logger = Logger.new(STDOUT, level: Logger::INFO)
|
19
|
-
# ref_resolver = SheetsV4::
|
19
|
+
# ref_resolver = SheetsV4::ApiObjectValidation::ResolveSchemaRef.new(logger:)
|
20
20
|
# people_schema = { 'type' => 'array', 'items' => { '$ref' => 'person' } }
|
21
21
|
# json_validator = JSONSchemer.schema(people_schema, ref_resolver:)
|
22
22
|
# people_json = [{ 'name' => { 'first' => 'John', 'last' => 'Doe' } }]
|
@@ -53,7 +53,7 @@ module SheetsV4
|
|
53
53
|
|
54
54
|
# Resolve a JSON schema reference
|
55
55
|
#
|
56
|
-
# @param ref [URI] the reference to resolve usually in the form "json-schemer://schema/
|
56
|
+
# @param ref [URI] the reference to resolve usually in the form "json-schemer://schema/[name]"
|
57
57
|
#
|
58
58
|
# @return [Hash] the schema object as a hash
|
59
59
|
#
|
@@ -62,7 +62,7 @@ module SheetsV4
|
|
62
62
|
def call(ref)
|
63
63
|
schema_name = ref.path[1..]
|
64
64
|
logger.debug { "Reading schema #{schema_name}" }
|
65
|
-
schemas = SheetsV4::
|
65
|
+
schemas = SheetsV4::ApiObjectValidation::LoadSchemas.new(logger:).call
|
66
66
|
schemas[schema_name].tap do |schema_object|
|
67
67
|
raise "Schema for #{ref} not found" unless schema_object
|
68
68
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SheetsV4
|
4
|
-
module
|
4
|
+
module ApiObjectValidation
|
5
5
|
# Visit all objects in arbitrarily nested object tree of hashes and/or arrays
|
6
6
|
#
|
7
7
|
# @api public
|
@@ -16,7 +16,7 @@ module SheetsV4
|
|
16
16
|
#
|
17
17
|
# ```Ruby
|
18
18
|
# visitor = -> (path:, object:) { puts "path: #{path}, object: #{obj}" }
|
19
|
-
# SheetsV4::
|
19
|
+
# SheetsV4::ApiObjectValidation::TraverseObjectTree.call(object:, visitor:)
|
20
20
|
# ```
|
21
21
|
#
|
22
22
|
# @example Given a simple object (not very exciting)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/inflector'
|
5
|
+
require 'json_schemer'
|
6
|
+
|
7
|
+
module SheetsV4
|
8
|
+
module ApiObjectValidation
|
9
|
+
# Validate objects against a Google Sheets API request object schema
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
#
|
13
|
+
class ValidateApiObject
|
14
|
+
# Create a new api object validator
|
15
|
+
#
|
16
|
+
# By default, a nil logger is used. This means that no messages are logged.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new
|
20
|
+
#
|
21
|
+
# @param logger [Logger] the logger to use
|
22
|
+
#
|
23
|
+
def initialize(logger: Logger.new(nil))
|
24
|
+
@logger = logger
|
25
|
+
end
|
26
|
+
|
27
|
+
# The logger to use internally
|
28
|
+
#
|
29
|
+
# Validation errors are logged at the error level. Other messages are logged
|
30
|
+
# at the debug level.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# logger = Logger.new(STDOUT, :level => Logger::INFO)
|
34
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new(logger)
|
35
|
+
# validator.logger == logger # => true
|
36
|
+
# validator.logger.debug { "Debug message" }
|
37
|
+
#
|
38
|
+
# @return [Logger]
|
39
|
+
#
|
40
|
+
attr_reader :logger
|
41
|
+
|
42
|
+
# Validate the object using the JSON schema named schema_name
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# schema_name = 'batch_update_spreadsheet_request'
|
46
|
+
# object = { 'requests' => [] }
|
47
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new
|
48
|
+
# validator.call(schema_name:, object:)
|
49
|
+
#
|
50
|
+
# @param schema_name [String] the name of the schema to validate against
|
51
|
+
# @param object [Object] the object to validate
|
52
|
+
#
|
53
|
+
# @raise [RuntimeError] if the object does not conform to the schema
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
#
|
57
|
+
def call(schema_name:, object:)
|
58
|
+
logger.debug { "Validating #{object} against #{schema_name}" }
|
59
|
+
|
60
|
+
schema = { '$ref' => schema_name }
|
61
|
+
schemer = JSONSchemer.schema(schema, ref_resolver:)
|
62
|
+
errors = schemer.validate(object)
|
63
|
+
raise_error!(schema_name, object, errors) if errors.any?
|
64
|
+
|
65
|
+
logger.debug { "Object #{object} conforms to #{schema_name}" }
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# The resolver to use to resolve JSON schema references
|
71
|
+
# @return [ResolveSchemaRef]
|
72
|
+
# @api private
|
73
|
+
def ref_resolver = @ref_resolver ||= SheetsV4::ApiObjectValidation::ResolveSchemaRef.new(logger:)
|
74
|
+
|
75
|
+
# Raise an error when the object does not conform to the schema
|
76
|
+
# @return [void]
|
77
|
+
# @raise [RuntimeError]
|
78
|
+
# @api private
|
79
|
+
def raise_error!(schema_name, object, errors)
|
80
|
+
error = errors.first['error']
|
81
|
+
error_message = "Object #{object} does not conform to #{schema_name}: #{error}"
|
82
|
+
logger.error(error_message)
|
83
|
+
raise error_message
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SheetsV4
|
4
|
+
# Validate API Objects against the Google Discovery API
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# logger = Logger.new(STDOUT, :level => Logger::ERROR)
|
8
|
+
# schema_name = 'batch_update_spreadsheet_request'
|
9
|
+
# object = { 'requests' => [] }
|
10
|
+
# SheetsV4::ApiObjectValidation::ValidateApiObject.new(logger:).call(schema_name:, object:)
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
module ApiObjectValidation; end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative 'api_object_validation/load_schemas'
|
18
|
+
require_relative 'api_object_validation/resolve_schema_ref'
|
19
|
+
require_relative 'api_object_validation/traverse_object_tree'
|
20
|
+
require_relative 'api_object_validation/validate_api_object'
|
data/lib/sheets_v4/color.rb
CHANGED
@@ -0,0 +1,243 @@
|
|
1
|
+
# Copyright (c) 2023 Yahoo
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'active_support'
|
6
|
+
require 'active_support/values/time_zone'
|
7
|
+
require 'active_support/core_ext/numeric/time'
|
8
|
+
require 'active_support/core_ext/string/zones'
|
9
|
+
|
10
|
+
module SheetsV4
|
11
|
+
# Convert between Ruby Date and DateTime objects and Google Sheets values
|
12
|
+
#
|
13
|
+
# Google Sheets uses decimal values to represent dates and times. These
|
14
|
+
# conversion routines allows converting from Ruby Date and DateTime objects
|
15
|
+
# and values that Google Sheets recognize.
|
16
|
+
#
|
17
|
+
# DateTime objects passed to `datetime_to_gs` or `date_to_gs` are converted to
|
18
|
+
# the time zone of the spreadsheet given in the initializer. DateTime objects
|
19
|
+
# returned by `gs_to_datetime` are always in the spreadsheet's time zone.
|
20
|
+
#
|
21
|
+
# Valid time zone names are those listed in one of these two sources:
|
22
|
+
# * `ActiveSupport::TimeZone.all.map { |tz| tz.tzinfo.name }`
|
23
|
+
# * `ActiveSupport::TimeZone.all.map(&:name)`
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# tz = spreadsheet.properties.time_zone #=> e.g. 'America/Los_Angeles'
|
27
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(tz)
|
28
|
+
# date = Date.parse('1967-03-15')
|
29
|
+
# converter.date_to_gs(date) #=> 24546
|
30
|
+
# converter.gs_to_date(24546) #=> #<Date: 1967-03-15 ((2439565j,0s,0n),+0s,2299161j)>
|
31
|
+
#
|
32
|
+
# date_time = DateTime.parse('2021-05-17 11:36:00 UTC')
|
33
|
+
# converter.datetime_to_gs(date_time) #=> 44333.191666666666
|
34
|
+
# converter.gs_to_datetime(44333.191666666666)
|
35
|
+
# #=> #<DateTime: 2021-05-17T11:36:00+00:00 ((2459352j,41760s,0n),+0s,2299161j)>
|
36
|
+
#
|
37
|
+
# @api public
|
38
|
+
#
|
39
|
+
class ConvertDatesAndTimes
|
40
|
+
# The time zone passed into the initializer
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# time_zone = 'UTC'
|
44
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
45
|
+
# converter.spreadsheet_tz
|
46
|
+
# #=> #<ActiveSupport::TimeZone:0x00007fe39000f908 @name="America/Los_Angeles", ...>
|
47
|
+
#
|
48
|
+
# @return [ActiveSupport::TimeZone] the time zone
|
49
|
+
#
|
50
|
+
attr_reader :spreadsheet_tz
|
51
|
+
|
52
|
+
# Initialize the conversion routines for a spreadsheet
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# time_zone = 'America/Los_Angeles'
|
56
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
57
|
+
#
|
58
|
+
# @param spreadsheet_tz [String] the time zone set in the spreadsheet properties
|
59
|
+
#
|
60
|
+
# @raise [RuntimeError] if the time zone is not valid
|
61
|
+
#
|
62
|
+
def initialize(spreadsheet_tz)
|
63
|
+
@spreadsheet_tz = ActiveSupport::TimeZone.new(spreadsheet_tz)
|
64
|
+
raise "Invalid time zone '#{spreadsheet_tz}'" unless @spreadsheet_tz
|
65
|
+
end
|
66
|
+
|
67
|
+
# Convert a Ruby DateTime object to a Google Sheets date time value
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# time_zone = 'America/Los_Angeles'
|
71
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
72
|
+
# date_time = DateTime.parse('2021-05-17 11:36:00 UTC')
|
73
|
+
# converter.datetime_to_gs(date_time) #=> 44333.191666666666
|
74
|
+
#
|
75
|
+
# @param datetime [DateTime, nil] the date and time to convert
|
76
|
+
#
|
77
|
+
# @return [Float, String] the value to store in a Google Sheets cell
|
78
|
+
# Returns a Float if datetime is not nil; otherwise, returns an empty string.
|
79
|
+
#
|
80
|
+
def datetime_to_gs(datetime)
|
81
|
+
return '' unless datetime
|
82
|
+
|
83
|
+
time = datetime.to_time.in_time_zone(spreadsheet_tz)
|
84
|
+
unix_to_gs_epoch(replace_time_zone(time, 'UTC').to_i)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convert a Google Sheets date time value to a DateTime object
|
88
|
+
#
|
89
|
+
# Time is rounded to the nearest second. The DateTime object returned is in
|
90
|
+
# the spreadsheet's time zone given in the initiaizer.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# time_zone = 'America/Los_Angeles'
|
94
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
95
|
+
# gs_value = 44333.191666666666
|
96
|
+
# converter.gs_to_datetime(gs_value) #=> #<DateTime: 2021-05-17T04:35:59-07:00 ...>
|
97
|
+
#
|
98
|
+
# @param gs_datetime [Float, "", nil] the value from the Google Sheets cell
|
99
|
+
#
|
100
|
+
# @return [DateTime, nil] the value represented by gs_datetime
|
101
|
+
# Returns a DateTime object if a Float was given; otherwise, returns nil if an
|
102
|
+
# empty string or nil was given.
|
103
|
+
#
|
104
|
+
def gs_to_datetime(gs_datetime)
|
105
|
+
return nil if gs_datetime.nil? || gs_datetime == ''
|
106
|
+
|
107
|
+
raise 'gs_datetime is a string' if gs_datetime.is_a?(String)
|
108
|
+
|
109
|
+
unix_epoch_datetime = gs_to_unix_epoch(gs_datetime.to_f)
|
110
|
+
time = Time.at_without_coercion(unix_epoch_datetime, in: 'UTC')
|
111
|
+
replace_time_zone(time, spreadsheet_tz).to_datetime
|
112
|
+
end
|
113
|
+
|
114
|
+
# Convert a Ruby Date object to a Google Sheets date value
|
115
|
+
#
|
116
|
+
# The Google Sheets date value is a float.
|
117
|
+
#
|
118
|
+
# @example with a Date object
|
119
|
+
# time_zone = 'America/Los_Angeles'
|
120
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
121
|
+
# date = Date.parse('2021-05-17')
|
122
|
+
# converter.date_to_gs(date) #=> 44333
|
123
|
+
#
|
124
|
+
# @example with a DateTime object
|
125
|
+
# time_zone = 'America/Los_Angeles'
|
126
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
127
|
+
# date_time = DateTime.parse('2021-05-17 11:36:00 UTC')
|
128
|
+
# converter.date_to_gs(date_time) #=> 44333
|
129
|
+
#
|
130
|
+
# @param date [DateTime, Date, nil] the date to convert
|
131
|
+
#
|
132
|
+
# @return [Float, String] the value to sstore in a Google Sheets cell
|
133
|
+
# Returns a Float if date is not nil; otherwise, returns an empty string
|
134
|
+
#
|
135
|
+
def date_to_gs(date)
|
136
|
+
return datetime_to_gs(date).to_i if date.is_a?(DateTime)
|
137
|
+
|
138
|
+
return (date - gs_epoch_start_date).to_i if date.is_a?(Date)
|
139
|
+
|
140
|
+
''
|
141
|
+
end
|
142
|
+
|
143
|
+
# Convert a Google Sheets date value to a Ruby Date object
|
144
|
+
#
|
145
|
+
# @example with a Date value
|
146
|
+
# time_zone = 'America/Los_Angeles'
|
147
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
148
|
+
# gs_value = 44333
|
149
|
+
# converter.gs_to_date(gs_value) #=> #<Date: 2021-05-17 ...>
|
150
|
+
#
|
151
|
+
# @example with a Date and Time value
|
152
|
+
# time_zone = 'America/Los_Angeles'
|
153
|
+
# converter = SheetsV4::ConvertDatesAndTimes.new(time_zone)
|
154
|
+
# gs_value = 44333.191666666666
|
155
|
+
# converter.gs_to_date(gs_value) #=> #<Date: 2021-05-17 ...>
|
156
|
+
#
|
157
|
+
# @param gs_date [Float, "", nil] the value from the Google Sheets cell
|
158
|
+
#
|
159
|
+
# @return [Date, nil] the value represented by gs_date
|
160
|
+
# Returns a Date object if a Float was given; otherwise, returns nil if an
|
161
|
+
# empty string or nil was given.
|
162
|
+
#
|
163
|
+
def gs_to_date(gs_date)
|
164
|
+
return nil if gs_date.nil? || gs_date == ''
|
165
|
+
|
166
|
+
raise 'gs_date is a string' if gs_date.is_a?(String)
|
167
|
+
|
168
|
+
(gs_epoch_start_date + gs_date.to_i)
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# The Google Sheets epoch start Date to use when calculating dates
|
174
|
+
# @return [Date] the 'zero' Date
|
175
|
+
# @api private
|
176
|
+
def gs_epoch_start_date
|
177
|
+
@gs_epoch_start_date ||= Date.parse('1899-12-30')
|
178
|
+
end
|
179
|
+
|
180
|
+
# The number of seconds in a day
|
181
|
+
#
|
182
|
+
# @return [Integer] number of seconds in a day
|
183
|
+
#
|
184
|
+
SECONDS_PER_DAY = 86_400
|
185
|
+
|
186
|
+
# The number of seconds between the Google Sheets Epoch and Unix Epoch
|
187
|
+
#
|
188
|
+
# Effectively the number of seconds between 1899-12-30 00:00:00 UTC and
|
189
|
+
# 1970-01-01 00:00:00 UTC.
|
190
|
+
#
|
191
|
+
# @return [Integer] the number of seconds
|
192
|
+
#
|
193
|
+
SECONDS_BETWEEN_GS_AND_UNIX_EPOCHS = 25_569 * 86_400
|
194
|
+
|
195
|
+
# Convert a gs_datetime to unix time
|
196
|
+
#
|
197
|
+
# @param gs_datetime [Float] time relative to the Google Sheets Epoch
|
198
|
+
#
|
199
|
+
# gs_datetime is a float representing the number of days since the start of
|
200
|
+
# the Google Sheets epoch (1899-12-30 00:00:00 UTC).
|
201
|
+
#
|
202
|
+
# @return [Integer] the same datetime in Unix Time rounded to the nearest second
|
203
|
+
#
|
204
|
+
# Unix time is an integer representing the number of seconds since the start of
|
205
|
+
# the Unix Epoch (1970-01-01 00:00:00 UTC). The number returned is rounded
|
206
|
+
# to the nearest second.
|
207
|
+
#
|
208
|
+
# @api private
|
209
|
+
#
|
210
|
+
def gs_to_unix_epoch(gs_datetime)
|
211
|
+
(gs_datetime * SECONDS_PER_DAY).round - SECONDS_BETWEEN_GS_AND_UNIX_EPOCHS
|
212
|
+
end
|
213
|
+
|
214
|
+
# Convert a unix time to gs_datetime
|
215
|
+
#
|
216
|
+
# @param unix_time [Integer] seconds since the Unix epoch 1970-01-01 00:00:00 UTC
|
217
|
+
#
|
218
|
+
# @return [Float] days since the Google Sheets epoch 1899-12-30 00:00:00 UTC
|
219
|
+
#
|
220
|
+
# @api private
|
221
|
+
#
|
222
|
+
def unix_to_gs_epoch(unix_time)
|
223
|
+
(unix_time + SECONDS_BETWEEN_GS_AND_UNIX_EPOCHS).to_f / SECONDS_PER_DAY
|
224
|
+
end
|
225
|
+
|
226
|
+
# Given a time, change the time zone without impacting the displayed date/time
|
227
|
+
#
|
228
|
+
# @example
|
229
|
+
# replace_time_zone(Time.parse('2021-05-21 11:40 UTC'), 'America/Los_Angeles')
|
230
|
+
# #=> '2021-05-21 11:40 -0700'
|
231
|
+
#
|
232
|
+
# @param time [Time] the time object to adjust
|
233
|
+
# @param time_zone_name [String] the desired time zone
|
234
|
+
#
|
235
|
+
# @return [Time] the resulting time object
|
236
|
+
#
|
237
|
+
# @api private
|
238
|
+
#
|
239
|
+
def replace_time_zone(time, time_zone_name)
|
240
|
+
time.asctime.in_time_zone(time_zone_name)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -5,7 +5,7 @@ require 'json_schemer'
|
|
5
5
|
module SheetsV4
|
6
6
|
# Creates a Google API credential with an access token
|
7
7
|
#
|
8
|
-
class
|
8
|
+
class CreateCredential
|
9
9
|
# Creates a Google API credential with an access token
|
10
10
|
#
|
11
11
|
# This wraps the boiler plate code into one function to make constructing a
|
@@ -14,7 +14,7 @@ module SheetsV4
|
|
14
14
|
# @example Constructing a credential from the contents of ~/.credential
|
15
15
|
# credential_source = File.read(File.join(Dir.home, '.credential'))
|
16
16
|
# scope = Google::Apis::SheetsV4::AUTH_SPREADSHEETS
|
17
|
-
# credential =
|
17
|
+
# credential = SheetsV4::CreateCredential.call(credential_source, scope)
|
18
18
|
#
|
19
19
|
# @param [Google::Auth::*, String, IO, nil] credential_source may be one of four things:
|
20
20
|
# (1) a previously created credential that you want to reuse, (2) a credential read
|
@@ -1,21 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support'
|
3
4
|
require 'active_support/inflector'
|
4
5
|
require 'json_schemer'
|
5
6
|
|
6
7
|
module SheetsV4
|
7
|
-
module
|
8
|
+
module ApiObjectValidation
|
8
9
|
# Validate objects against a Google Sheets API request object schema
|
9
10
|
#
|
10
11
|
# @api public
|
11
12
|
#
|
12
|
-
class
|
13
|
+
class ValidateApiObject
|
13
14
|
# Create a new validator
|
14
15
|
#
|
15
16
|
# By default, a nil logger is used. This means that no messages are logged.
|
16
17
|
#
|
17
18
|
# @example
|
18
|
-
# validator = SheetsV4::
|
19
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new
|
19
20
|
#
|
20
21
|
# @param logger [Logger] the logger to use
|
21
22
|
#
|
@@ -30,7 +31,7 @@ module SheetsV4
|
|
30
31
|
#
|
31
32
|
# @example
|
32
33
|
# logger = Logger.new(STDOUT, :level => Logger::INFO)
|
33
|
-
# validator = SheetsV4::
|
34
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new(logger)
|
34
35
|
# validator.logger == logger # => true
|
35
36
|
# validator.logger.debug { "Debug message" }
|
36
37
|
#
|
@@ -43,7 +44,7 @@ module SheetsV4
|
|
43
44
|
# @example
|
44
45
|
# schema_name = 'batch_update_spreadsheet_request'
|
45
46
|
# object = { 'requests' => [] }
|
46
|
-
# validator = SheetsV4::
|
47
|
+
# validator = SheetsV4::ApiObjectValidation::ValidateApiObject.new
|
47
48
|
# validator.call(schema_name:, object:)
|
48
49
|
#
|
49
50
|
# @param schema_name [String] the name of the schema to validate against
|
@@ -69,7 +70,7 @@ module SheetsV4
|
|
69
70
|
# The resolver to use to resolve JSON schema references
|
70
71
|
# @return [ResolveSchemaRef]
|
71
72
|
# @api private
|
72
|
-
def ref_resolver = @ref_resolver ||= SheetsV4::
|
73
|
+
def ref_resolver = @ref_resolver ||= SheetsV4::ApiObjectValidation::ResolveSchemaRef.new(logger:)
|
73
74
|
|
74
75
|
# Raise an error when the object does not conform to the schema
|
75
76
|
# @return [void]
|
@@ -7,14 +7,14 @@ module SheetsV4
|
|
7
7
|
# logger = Logger.new(STDOUT, :level => Logger::ERROR)
|
8
8
|
# schema_name = 'batch_update_spreadsheet_request'
|
9
9
|
# object = { 'requests' => [] }
|
10
|
-
# SheetsV4::
|
10
|
+
# SheetsV4::ApiObjectValidation::ValidateApiObject.new(logger:).call(schema_name:, object:)
|
11
11
|
#
|
12
12
|
# @api public
|
13
13
|
#
|
14
|
-
module
|
14
|
+
module ApiObjectValidation; end
|
15
15
|
end
|
16
16
|
|
17
|
-
require_relative '
|
18
|
-
require_relative '
|
19
|
-
require_relative '
|
20
|
-
require_relative '
|
17
|
+
require_relative 'api_object_validation/load_schemas'
|
18
|
+
require_relative 'api_object_validation/resolve_schema_ref'
|
19
|
+
require_relative 'api_object_validation/traverse_object_tree'
|
20
|
+
require_relative 'api_object_validation/validate_api_object'
|
data/lib/sheets_v4/version.rb
CHANGED
data/lib/sheets_v4.rb
CHANGED
@@ -2,9 +2,14 @@
|
|
2
2
|
|
3
3
|
require_relative 'sheets_v4/version'
|
4
4
|
require_relative 'sheets_v4/color'
|
5
|
-
require_relative 'sheets_v4/
|
6
|
-
require_relative 'sheets_v4/
|
5
|
+
require_relative 'sheets_v4/convert_dates_and_times'
|
6
|
+
require_relative 'sheets_v4/create_credential'
|
7
|
+
require_relative 'sheets_v4/api_object_validation'
|
7
8
|
|
9
|
+
require 'active_support'
|
10
|
+
require 'active_support/values/time_zone'
|
11
|
+
require 'active_support/core_ext/numeric/time'
|
12
|
+
require 'active_support/core_ext/string/zones'
|
8
13
|
require 'google/apis/sheets_v4'
|
9
14
|
require 'json'
|
10
15
|
require 'logger'
|
@@ -15,102 +20,221 @@ require 'net/http'
|
|
15
20
|
# @api public
|
16
21
|
#
|
17
22
|
module SheetsV4
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
credential_source
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
23
|
+
class << self
|
24
|
+
# Create a new Google::Apis::SheetsV4::SheetsService object
|
25
|
+
#
|
26
|
+
# Simplifies creating and configuring a the credential.
|
27
|
+
#
|
28
|
+
# @example using the credential in `~/.google-api-credential`
|
29
|
+
# SheetsV4.sheets_service
|
30
|
+
#
|
31
|
+
# @example using a credential passed in as a string
|
32
|
+
# credential_source = File.read(File.expand_path('~/.google-api-credential.json'))
|
33
|
+
# SheetsV4.sheets_service(credential_source:)
|
34
|
+
#
|
35
|
+
# @example using a credential passed in as an IO
|
36
|
+
# credential_source = File.open(File.expand_path('~/.google-api-credential.json'))
|
37
|
+
# SheetsV4.sheets_service(credential_source:)
|
38
|
+
#
|
39
|
+
# @param credential_source [nil, String, IO, Google::Auth::*] may
|
40
|
+
# be either an already constructed credential, the credential read into a String or
|
41
|
+
# an open file with the credential ready to be read. Passing `nil` will result
|
42
|
+
# in the credential being read from `~/.google-api-credential.json`.
|
43
|
+
#
|
44
|
+
# @param scopes [Object, Array] one or more scopes to access.
|
45
|
+
#
|
46
|
+
# @param credential_creator [#credential] Used to inject the credential creator for
|
47
|
+
# testing.
|
48
|
+
#
|
49
|
+
# @return a new SheetsService instance
|
50
|
+
#
|
51
|
+
def sheets_service(credential_source: nil, scopes: nil, credential_creator: SheetsV4::CreateCredential)
|
52
|
+
credential_source ||= File.read(File.expand_path('~/.google-api-credential.json'))
|
53
|
+
scopes ||= [Google::Apis::SheetsV4::AUTH_SPREADSHEETS]
|
54
|
+
|
55
|
+
Google::Apis::SheetsV4::SheetsService.new.tap do |service|
|
56
|
+
service.authorization = credential_creator.call(credential_source, scopes)
|
57
|
+
end
|
51
58
|
end
|
52
|
-
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
# Validate the object using the named JSON schema
|
61
|
+
#
|
62
|
+
# The JSON schemas are loaded from the Google Disocvery API. The schemas names are
|
63
|
+
# returned by `SheetsV4.api_object_schema_names`.
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# schema_name = 'batch_update_spreadsheet_request'
|
67
|
+
# object = { 'requests' => [] }
|
68
|
+
# SheetsV4.validate_api_object(schema_name:, object:)
|
69
|
+
#
|
70
|
+
# @param schema_name [String] the name of the schema to validate against
|
71
|
+
# @param object [Object] the object to validate
|
72
|
+
# @param logger [Logger] the logger to use for logging error, info, and debug message
|
73
|
+
#
|
74
|
+
# @raise [RuntimeError] if the object does not conform to the schema
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
#
|
78
|
+
def validate_api_object(schema_name:, object:, logger: Logger.new(nil))
|
79
|
+
SheetsV4::ApiObjectValidation::ValidateApiObject.new(logger:).call(schema_name:, object:)
|
80
|
+
end
|
75
81
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
# List the names of the schemas available to use in the Google Sheets API
|
83
|
+
#
|
84
|
+
# @example List the name of the schemas available
|
85
|
+
# SheetsV4.api_object_schema_names #=> ["add_banding_request", "add_banding_response", ...]
|
86
|
+
#
|
87
|
+
# @return [Array<String>] the names of the schemas available
|
88
|
+
#
|
89
|
+
def api_object_schema_names(logger: Logger.new(nil))
|
90
|
+
SheetsV4::ApiObjectValidation::LoadSchemas.new(logger:).call.keys.sort
|
91
|
+
end
|
86
92
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
93
|
+
# Given the name of the color, return a Google Sheets API color object
|
94
|
+
#
|
95
|
+
# Available color names are listed using `SheetsV4.color_names`.
|
96
|
+
#
|
97
|
+
# The object returned is frozen. If you want a color you can change (for instance,
|
98
|
+
# to adjust the `alpha` attribute), you must clone the object returned.
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# SheetsV4::Color.color(:red) #=> { "red": 1.0, "green": 0.0, "blue": 0.0 }
|
102
|
+
#
|
103
|
+
# @param name [#to_sym] the name of the color requested
|
104
|
+
#
|
105
|
+
# @return [Hash] The color requested e.g. `{ "red": 1.0, "green": 0.0, "blue": 0.0 }`
|
106
|
+
#
|
107
|
+
def color(name)
|
108
|
+
SheetsV4::Color::COLORS[name.to_sym] || raise("Color #{name} not found")
|
109
|
+
end
|
110
|
+
|
111
|
+
# List the names of the colors available to use in the Google Sheets API
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# SheetsV4::Color.color_names #=> [:black, :white, :red, :green, :blue, :yellow, :magenta, :cyan, ...]
|
115
|
+
#
|
116
|
+
# @return [Array<Symbol>] the names of the colors available
|
117
|
+
#
|
118
|
+
def color_names = SheetsV4::Color::COLORS.keys
|
119
|
+
|
120
|
+
# @!attribute [rw] default_spreadsheet_tz
|
121
|
+
#
|
122
|
+
# Set the default time zone for date and time conversions
|
123
|
+
#
|
124
|
+
# Valid time zone names are those listed in one of these two sources:
|
125
|
+
# * `ActiveSupport::TimeZone.all.map { |tz| tz.tzinfo.name }`
|
126
|
+
# * `ActiveSupport::TimeZone.all.map(&:name)`
|
127
|
+
#
|
128
|
+
# If you want to set the timezone to the time zone of the system's local time,
|
129
|
+
# you could use the [timezone_local gem](https://rubygems.org/gems/timezone_local).
|
130
|
+
#
|
131
|
+
# @example
|
132
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
133
|
+
#
|
134
|
+
# @example Set the time zone to the system's local time
|
135
|
+
# require 'timezone_local'
|
136
|
+
# SheetsV4.default_spreadsheet_tz = TimeZone::Local.get.name
|
137
|
+
#
|
138
|
+
# @return [void]
|
139
|
+
#
|
140
|
+
def default_spreadsheet_tz
|
141
|
+
@default_spreadsheet_tz || raise('default_spreadsheet_tz not set')
|
142
|
+
end
|
143
|
+
|
144
|
+
def default_spreadsheet_tz=(time_zone)
|
145
|
+
raise "Invalid time zone '#{time_zone}'" unless ActiveSupport::TimeZone.new(time_zone)
|
106
146
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
147
|
+
@default_date_and_time_converter = nil unless @default_spreadsheet_tz == time_zone
|
148
|
+
@default_spreadsheet_tz = time_zone
|
149
|
+
end
|
150
|
+
|
151
|
+
# The default converter for dates and times
|
152
|
+
# @return [SheetsV4::ConvertDatesAndTimes]
|
153
|
+
# @api private
|
154
|
+
def default_date_and_time_converter
|
155
|
+
@default_date_and_time_converter ||= SheetsV4::ConvertDatesAndTimes.new(default_spreadsheet_tz)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Convert a Ruby Date object to a Google Sheet date value
|
159
|
+
#
|
160
|
+
# Uses the time zone given by `SheetsV4.default_spreadsheet_tz`.
|
161
|
+
#
|
162
|
+
# @example with a Date object
|
163
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
164
|
+
# date = Date.parse('2021-05-17')
|
165
|
+
# SheetsV4.date_to_gs(date) #=> 44333
|
166
|
+
#
|
167
|
+
# @example with a DateTime object
|
168
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
169
|
+
# date_time = DateTime.parse('2021-05-17 11:36:00 UTC')
|
170
|
+
# SheetsV4.date_to_gs(date_time) #=> 44333
|
171
|
+
#
|
172
|
+
# @param date [DateTime, Date, nil] the date to convert
|
173
|
+
#
|
174
|
+
# @return [Float, String] the value to sstore in a Google Sheet cell
|
175
|
+
# Returns a Float if date is not nil; otherwise, returns an empty string
|
176
|
+
#
|
177
|
+
def date_to_gs(date)
|
178
|
+
default_date_and_time_converter.date_to_gs(date)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Convert a Google Sheets date value to a Ruby Date object
|
182
|
+
#
|
183
|
+
# @example with a date value
|
184
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
185
|
+
# gs_value = 44333
|
186
|
+
# SheetsV4.gs_to_date(gs_value) #=> #<Date: 2021-05-17 ...>
|
187
|
+
#
|
188
|
+
# @example with a date and time value
|
189
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
190
|
+
# gs_value = 44333.191666666666
|
191
|
+
# SheetsV4.gs_to_date(gs_value) #=> #<Date: 2021-05-17 ...>
|
192
|
+
#
|
193
|
+
# @param gs_value [Float, "", nil] the value from the Google Sheets cell
|
194
|
+
#
|
195
|
+
# @return [Date, nil] the value represented by gs_date
|
196
|
+
#
|
197
|
+
# Returns a Date object if a Float was given; otherwise, returns nil if an
|
198
|
+
# empty string or nil was given.
|
199
|
+
#
|
200
|
+
def gs_to_date(gs_value)
|
201
|
+
default_date_and_time_converter.gs_to_date(gs_value)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Convert a Ruby DateTime object to a Google Sheets value
|
205
|
+
#
|
206
|
+
# @example
|
207
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
208
|
+
# date_time = DateTime.parse('2021-05-17 11:36:00 UTC')
|
209
|
+
# SheetsV4.datetime_to_gs(date_time) #=> 44333.191666666666
|
210
|
+
#
|
211
|
+
# @param datetime [DateTime, nil] the date and time to convert
|
212
|
+
#
|
213
|
+
# @return [Float, String] the value to store in a Google Sheet cell
|
214
|
+
# Returns a Float if datetime is not nil; otherwise, returns an empty string.
|
215
|
+
#
|
216
|
+
def datetime_to_gs(datetime)
|
217
|
+
default_date_and_time_converter.datetime_to_gs(datetime)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Convert a Google Sheets date time value to a DateTime object
|
221
|
+
#
|
222
|
+
# Time is rounded to the nearest second. The DateTime object returned is in
|
223
|
+
# the time zone given by `SheetsV4.default_spreadsheet_tz`.
|
224
|
+
#
|
225
|
+
# @example
|
226
|
+
# SheetsV4.default_spreadsheet_tz = 'America/Los_Angeles'
|
227
|
+
# gs_value = 44333.191666666666
|
228
|
+
# SheetsV4.gs_to_datetime(gs_value) #=> #<DateTime: 2021-05-17T04:35:59-07:00 ...>
|
229
|
+
#
|
230
|
+
# @param gs_value [Float, "", nil] the value from the Google Sheets cell
|
231
|
+
#
|
232
|
+
# @return [DateTime, nil] the value represented by gs_datetime
|
233
|
+
# Returns a DateTime object if a Float was given; otherwise, returns nil if an
|
234
|
+
# empty string or nil was given.
|
235
|
+
#
|
236
|
+
def gs_to_datetime(gs_value)
|
237
|
+
default_date_and_time_converter.gs_to_datetime(gs_value)
|
238
|
+
end
|
239
|
+
end
|
116
240
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sheets_v4
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Couball
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler-audit
|
@@ -260,13 +260,16 @@ files:
|
|
260
260
|
- examples/set_background_color
|
261
261
|
- examples/set_background_color2
|
262
262
|
- lib/sheets_v4.rb
|
263
|
+
- lib/sheets_v4/api_object_validation.rb
|
264
|
+
- lib/sheets_v4/api_object_validation/load_schemas.rb
|
265
|
+
- lib/sheets_v4/api_object_validation/resolve_schema_ref.rb
|
266
|
+
- lib/sheets_v4/api_object_validation/traverse_object_tree.rb
|
267
|
+
- lib/sheets_v4/api_object_validation/validate_api_object.rb
|
263
268
|
- lib/sheets_v4/color.rb
|
264
|
-
- lib/sheets_v4/
|
269
|
+
- lib/sheets_v4/convert_dates_and_times.rb
|
270
|
+
- lib/sheets_v4/create_credential.rb
|
265
271
|
- lib/sheets_v4/validate_api_objects.rb
|
266
|
-
- lib/sheets_v4/validate_api_objects/
|
267
|
-
- lib/sheets_v4/validate_api_objects/resolve_schema_ref.rb
|
268
|
-
- lib/sheets_v4/validate_api_objects/traverse_object_tree.rb
|
269
|
-
- lib/sheets_v4/validate_api_objects/validate.rb
|
272
|
+
- lib/sheets_v4/validate_api_objects/validate_api_object.rb
|
270
273
|
- lib/sheets_v4/version.rb
|
271
274
|
homepage: https://github.com/main-branch/sheets_v4
|
272
275
|
licenses:
|