rbs 0.20.1 → 1.0.0.pre
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/Rakefile +4 -0
- data/core/builtin.rbs +4 -0
- data/core/io.rbs +159 -6
- data/core/kernel.rbs +1 -1
- data/goodcheck.yml +20 -0
- data/lib/rbs.rb +2 -0
- data/lib/rbs/ast/declarations.rb +7 -2
- data/lib/rbs/ast/members.rb +1 -1
- data/lib/rbs/cli.rb +10 -10
- data/lib/rbs/definition.rb +70 -3
- data/lib/rbs/definition_builder.rb +542 -1006
- data/lib/rbs/definition_builder/ancestor_builder.rb +476 -0
- data/lib/rbs/definition_builder/method_builder.rb +217 -0
- data/lib/rbs/environment.rb +2 -1
- data/lib/rbs/errors.rb +71 -66
- data/lib/rbs/parser.rb +673 -627
- data/lib/rbs/parser.y +13 -2
- data/lib/rbs/prototype/rb.rb +1 -1
- data/lib/rbs/prototype/rbi.rb +1 -1
- data/lib/rbs/prototype/runtime.rb +52 -32
- data/lib/rbs/substitution.rb +4 -0
- data/lib/rbs/test.rb +3 -1
- data/lib/rbs/test/hook.rb +20 -6
- data/lib/rbs/validator.rb +4 -2
- data/lib/rbs/variance_calculator.rb +5 -1
- data/lib/rbs/version.rb +1 -1
- data/sig/definition.rbs +6 -1
- data/sig/errors.rbs +20 -0
- data/sig/type_name_resolver.rbs +4 -2
- data/sig/validator.rbs +12 -0
- data/stdlib/logger/0/log_device.rbs +1 -2
- data/stdlib/time/0/time.rbs +327 -0
- data/stdlib/uri/0/common.rbs +401 -0
- data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
- data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
- data/steep/Gemfile.lock +10 -11
- metadata +13 -5
data/lib/rbs/parser.y
CHANGED
@@ -99,11 +99,13 @@ rule
|
|
99
99
|
{ result = nil }
|
100
100
|
| kLT class_name {
|
101
101
|
result = Declarations::Class::Super.new(name: val[1].value,
|
102
|
-
args: []
|
102
|
+
args: [],
|
103
|
+
location: val[1].location)
|
103
104
|
}
|
104
105
|
| kLT class_name kLBRACKET type_list kRBRACKET {
|
105
106
|
result = Declarations::Class::Super.new(name: val[1].value,
|
106
|
-
args: val[3]
|
107
|
+
args: val[3],
|
108
|
+
location: val[1].location + val[4].location)
|
107
109
|
}
|
108
110
|
|
109
111
|
module_decl:
|
@@ -839,6 +841,15 @@ rule
|
|
839
841
|
| keyword type {
|
840
842
|
result = { val[0].value => val[1] }
|
841
843
|
}
|
844
|
+
| identifier_keywords kCOLON type {
|
845
|
+
result = { val[0].value => val[2] }
|
846
|
+
}
|
847
|
+
| tQUOTEDIDENT kCOLON type {
|
848
|
+
result = { val[0].value => val[2] }
|
849
|
+
}
|
850
|
+
| tQUOTEDMETHOD kCOLON type {
|
851
|
+
result = { val[0].value => val[2] }
|
852
|
+
}
|
842
853
|
|
843
854
|
keyword_name:
|
844
855
|
keyword
|
data/lib/rbs/prototype/rb.rb
CHANGED
@@ -85,7 +85,7 @@ module RBS
|
|
85
85
|
class_name, super_class, *class_body = node.children
|
86
86
|
kls = AST::Declarations::Class.new(
|
87
87
|
name: const_to_name(class_name),
|
88
|
-
super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: []),
|
88
|
+
super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
|
89
89
|
type_params: AST::Declarations::ModuleTypeParams.empty,
|
90
90
|
members: [],
|
91
91
|
annotations: [],
|
data/lib/rbs/prototype/rbi.rb
CHANGED
@@ -47,7 +47,7 @@ module RBS
|
|
47
47
|
def push_class(name, super_class, comment:)
|
48
48
|
modules.push AST::Declarations::Class.new(
|
49
49
|
name: nested_name(name),
|
50
|
-
super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: []),
|
50
|
+
super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
|
51
51
|
type_params: AST::Declarations::ModuleTypeParams.empty,
|
52
52
|
members: [],
|
53
53
|
annotations: [],
|
@@ -61,11 +61,32 @@ module RBS
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
65
|
-
supers = Set
|
66
|
-
|
64
|
+
def each_included_module(type_name, mod)
|
65
|
+
supers = Set[]
|
66
|
+
|
67
|
+
mod.included_modules.each do |mix|
|
68
|
+
supers.merge(mix.included_modules)
|
69
|
+
end
|
70
|
+
|
71
|
+
if mod.is_a?(Class)
|
72
|
+
mod.superclass.included_modules.each do |mix|
|
73
|
+
supers << mix
|
74
|
+
supers.merge(mix.included_modules)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
mod.included_modules.each do |mix|
|
67
79
|
unless supers.include?(mix)
|
68
|
-
|
80
|
+
unless const_name(mix)
|
81
|
+
RBS.logger.warn("Skipping anonymous module #{mix} included in #{mod}")
|
82
|
+
else
|
83
|
+
module_name = to_type_name(const_name(mix))
|
84
|
+
if module_name.namespace == type_name.namespace
|
85
|
+
module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
|
86
|
+
end
|
87
|
+
|
88
|
+
yield module_name, mix
|
89
|
+
end
|
69
90
|
end
|
70
91
|
end
|
71
92
|
end
|
@@ -298,11 +319,11 @@ module RBS
|
|
298
319
|
location: nil
|
299
320
|
)
|
300
321
|
else
|
301
|
-
Types::ClassInstance.new(name: to_type_name(value.class
|
322
|
+
Types::ClassInstance.new(name: to_type_name(const_name(value.class)), args: [], location: nil)
|
302
323
|
end
|
303
324
|
|
304
325
|
@decls << AST::Declarations::Constant.new(
|
305
|
-
name: "#{mod
|
326
|
+
name: "#{const_name(mod)}::#{name}",
|
306
327
|
type: type,
|
307
328
|
location: nil,
|
308
329
|
comment: nil
|
@@ -311,14 +332,14 @@ module RBS
|
|
311
332
|
end
|
312
333
|
|
313
334
|
def generate_class(mod)
|
314
|
-
type_name = to_type_name(mod
|
335
|
+
type_name = to_type_name(const_name(mod))
|
315
336
|
super_class = if mod.superclass == ::Object
|
316
337
|
nil
|
317
|
-
elsif mod.superclass.
|
338
|
+
elsif const_name(mod.superclass).nil?
|
318
339
|
RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
|
319
340
|
nil
|
320
341
|
else
|
321
|
-
AST::Declarations::Class::Super.new(name: to_type_name(mod.superclass
|
342
|
+
AST::Declarations::Class::Super.new(name: to_type_name(const_name(mod.superclass)), args: [], location: nil)
|
322
343
|
end
|
323
344
|
|
324
345
|
decl = AST::Declarations::Class.new(
|
@@ -331,17 +352,7 @@ module RBS
|
|
331
352
|
comment: nil
|
332
353
|
)
|
333
354
|
|
334
|
-
|
335
|
-
unless included_module.name
|
336
|
-
RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
|
337
|
-
next
|
338
|
-
end
|
339
|
-
|
340
|
-
module_name = to_type_name(included_module.name)
|
341
|
-
if module_name.namespace == type_name.namespace
|
342
|
-
module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
|
343
|
-
end
|
344
|
-
|
355
|
+
each_included_module(type_name, mod) do |module_name, _|
|
345
356
|
decl.members << AST::Members::Include.new(
|
346
357
|
name: module_name,
|
347
358
|
args: [],
|
@@ -351,6 +362,16 @@ module RBS
|
|
351
362
|
)
|
352
363
|
end
|
353
364
|
|
365
|
+
each_included_module(type_name, mod.singleton_class) do |module_name, _|
|
366
|
+
decl.members << AST::Members::Extend.new(
|
367
|
+
name: module_name,
|
368
|
+
args: [],
|
369
|
+
location: nil,
|
370
|
+
comment: nil,
|
371
|
+
annotations: []
|
372
|
+
)
|
373
|
+
end
|
374
|
+
|
354
375
|
generate_methods(mod, type_name, decl.members)
|
355
376
|
|
356
377
|
@decls << decl
|
@@ -378,18 +399,7 @@ module RBS
|
|
378
399
|
comment: nil
|
379
400
|
)
|
380
401
|
|
381
|
-
|
382
|
-
included_module_name = const_name(included_module)
|
383
|
-
unless included_module_name
|
384
|
-
RBS.logger.warn("Skipping anonymous module #{included_module} included in #{mod}")
|
385
|
-
next
|
386
|
-
end
|
387
|
-
|
388
|
-
module_name = to_type_name(included_module_name)
|
389
|
-
if module_name.namespace == type_name.namespace
|
390
|
-
module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
|
391
|
-
end
|
392
|
-
|
402
|
+
each_included_module(type_name, mod) do |module_name, _|
|
393
403
|
decl.members << AST::Members::Include.new(
|
394
404
|
name: module_name,
|
395
405
|
args: [],
|
@@ -399,6 +409,16 @@ module RBS
|
|
399
409
|
)
|
400
410
|
end
|
401
411
|
|
412
|
+
each_included_module(type_name, mod.singleton_class) do |module_name, _|
|
413
|
+
decl.members << AST::Members::Extend.new(
|
414
|
+
name: module_name,
|
415
|
+
args: [],
|
416
|
+
location: nil,
|
417
|
+
comment: nil,
|
418
|
+
annotations: []
|
419
|
+
)
|
420
|
+
end
|
421
|
+
|
402
422
|
generate_methods(mod, type_name, decl.members)
|
403
423
|
|
404
424
|
@decls << decl
|
data/lib/rbs/substitution.rb
CHANGED
data/lib/rbs/test.rb
CHANGED
data/lib/rbs/test/hook.rb
CHANGED
@@ -67,12 +67,19 @@ module RBS
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
def self.hook_method_source(prefix, method_name, key, random:)
|
70
|
+
def self.hook_method_source(prefix, method_name, key, random:, params:)
|
71
71
|
with_name, without_name = alias_names(method_name, random)
|
72
72
|
full_method_name = "#{prefix}#{method_name}"
|
73
73
|
|
74
|
+
param_source = params.take_while {|param| param[0] == :req }.map(&:last) + ["*rest_args_#{random}"]
|
75
|
+
|
76
|
+
RBS.logger.debug {
|
77
|
+
"Generating method definition: def #{with_name}(#{param_source.join(", ")}, &block) ..."
|
78
|
+
}
|
79
|
+
|
74
80
|
[__LINE__ + 1, <<RUBY]
|
75
|
-
def #{with_name}(
|
81
|
+
def #{with_name}(#{param_source.join(", ")}, &block)
|
82
|
+
args = [#{param_source.join(", ")}]
|
76
83
|
::RBS.logger.debug { "#{full_method_name} with arguments: [" + args.map(&:inspect).join(", ") + "]" }
|
77
84
|
|
78
85
|
begin
|
@@ -81,13 +88,18 @@ def #{with_name}(*args, &block)
|
|
81
88
|
|
82
89
|
if block_given?
|
83
90
|
receiver = self
|
91
|
+
block_receives_block = block.parameters.last&.yield_self {|type, _| type == :block }
|
84
92
|
|
85
|
-
wrapped_block = proc do |*block_args|
|
93
|
+
wrapped_block = proc do |*block_args, &block2|
|
86
94
|
return_from_block = false
|
87
95
|
|
88
96
|
begin
|
89
97
|
block_result = if receiver.equal?(self)
|
90
|
-
|
98
|
+
if block_receives_block
|
99
|
+
block.call(*block_args, &block2)
|
100
|
+
else
|
101
|
+
yield(*block_args)
|
102
|
+
end
|
91
103
|
else
|
92
104
|
instance_exec(*block_args, &block)
|
93
105
|
end
|
@@ -166,7 +178,8 @@ RUBY
|
|
166
178
|
|
167
179
|
def self.hook_instance_method(klass, method, key:)
|
168
180
|
random = SecureRandom.hex(4)
|
169
|
-
|
181
|
+
params = klass.instance_method(method).parameters
|
182
|
+
line, source = hook_method_source("#{klass}#", method, key, random: random, params: params)
|
170
183
|
|
171
184
|
klass.module_eval(source, __FILE__, line)
|
172
185
|
setup_alias_method_chain klass, method, random: random
|
@@ -174,7 +187,8 @@ RUBY
|
|
174
187
|
|
175
188
|
def self.hook_singleton_method(klass, method, key:)
|
176
189
|
random = SecureRandom.hex(4)
|
177
|
-
|
190
|
+
params = klass.method(method).parameters
|
191
|
+
line, source = hook_method_source("#{klass}.",method, key, random: random, params: params)
|
178
192
|
|
179
193
|
klass.singleton_class.module_eval(source, __FILE__, line)
|
180
194
|
setup_alias_method_chain klass.singleton_class, method, random: random
|
data/lib/rbs/validator.rb
CHANGED
@@ -18,8 +18,9 @@ module RBS
|
|
18
18
|
def validate_type(type, context:)
|
19
19
|
case type
|
20
20
|
when Types::ClassInstance, Types::Interface
|
21
|
+
# @type var type: Types::ClassInstance | Types::Interface
|
21
22
|
if type.name.namespace.relative?
|
22
|
-
type = absolute_type(type, context: context) do |
|
23
|
+
type = _ = absolute_type(type, context: context) do |_|
|
23
24
|
NoTypeFoundError.check!(type.name.absolute!, env: env, location: type.location)
|
24
25
|
end
|
25
26
|
end
|
@@ -43,7 +44,8 @@ module RBS
|
|
43
44
|
)
|
44
45
|
|
45
46
|
when Types::Alias, Types::ClassSingleton
|
46
|
-
type
|
47
|
+
# @type var type: Types::Alias | Types::ClassSingleton
|
48
|
+
type = _ = absolute_type(type, context: context) { type.name.absolute! }
|
47
49
|
NoTypeFoundError.check!(type.name, env: env, location: type.location)
|
48
50
|
end
|
49
51
|
|
@@ -86,7 +86,11 @@ module RBS
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def in_inherit(name:, args:, variables:)
|
89
|
-
type =
|
89
|
+
type = if name.class?
|
90
|
+
Types::ClassInstance.new(name: name, args: args, location: nil)
|
91
|
+
else
|
92
|
+
Types::Interface.new(name: name, args: args, location: nil)
|
93
|
+
end
|
90
94
|
|
91
95
|
Result.new(variables: variables).tap do |result|
|
92
96
|
type(type, result: result, context: :covariant)
|
data/lib/rbs/version.rb
CHANGED
data/sig/definition.rbs
CHANGED
@@ -65,10 +65,15 @@ module RBS
|
|
65
65
|
type t = Instance | Singleton
|
66
66
|
|
67
67
|
class Instance
|
68
|
+
type source = :super | nil
|
69
|
+
| AST::Members::Include | AST::Members::Extend | AST::Members::Prepend
|
70
|
+
| AST::Declarations::Module::Self
|
71
|
+
|
68
72
|
attr_reader name: TypeName
|
69
73
|
attr_reader args: Array[Types::t]
|
74
|
+
attr_reader source: source
|
70
75
|
|
71
|
-
def initialize: (name: TypeName, args: Array[Types::t]) -> void
|
76
|
+
def initialize: (name: TypeName, args: Array[Types::t], source: source) -> void
|
72
77
|
end
|
73
78
|
|
74
79
|
class Singleton
|
data/sig/errors.rbs
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module RBS
|
2
|
+
interface _Kinded
|
3
|
+
def kind: () -> (:instance | :singleton)
|
4
|
+
end
|
5
|
+
|
6
|
+
module MethodNameHelper : _Kinded
|
7
|
+
def method_name_string: () -> String
|
8
|
+
end
|
9
|
+
|
10
|
+
class InvalidTypeApplicationError < StandardError
|
11
|
+
attr_reader type_name: TypeName
|
12
|
+
attr_reader args: Array[Types::t]
|
13
|
+
attr_reader params: Array[Symbol]
|
14
|
+
attr_reader location: Location?
|
15
|
+
|
16
|
+
def initialize: (type_name: TypeName, args: Array[Types::t], params: Array[Symbol], location: Location?) -> void
|
17
|
+
|
18
|
+
def self.check!: (type_name: TypeName, args: Array[Types::t], params: Array[Symbol], location: Location?) -> void
|
19
|
+
end
|
20
|
+
end
|
data/sig/type_name_resolver.rbs
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
module RBS
|
2
2
|
class TypeNameResolver
|
3
|
+
type context = Array[Namespace]
|
4
|
+
|
3
5
|
class Query
|
4
6
|
attr_reader type_name: TypeName
|
5
7
|
attr_reader context: Array[Namespace]
|
6
8
|
|
7
|
-
def initialize: (type_name: TypeName, context:
|
9
|
+
def initialize: (type_name: TypeName, context: context) -> void
|
8
10
|
end
|
9
11
|
|
10
12
|
attr_reader all_names: Set[TypeName]
|
@@ -15,7 +17,7 @@ module RBS
|
|
15
17
|
|
16
18
|
def add_names: (Array[TypeName]) -> self
|
17
19
|
|
18
|
-
def resolve: (TypeName, context:
|
20
|
+
def resolve: (TypeName, context: context) -> TypeName?
|
19
21
|
|
20
22
|
def has_name?: (TypeName) -> TypeName?
|
21
23
|
|
data/sig/validator.rbs
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module RBS
|
2
|
+
class Validator
|
3
|
+
attr_reader env: Environment
|
4
|
+
attr_reader resolver: TypeNameResolver
|
5
|
+
|
6
|
+
def initialize: (env: Environment, resolver: TypeNameResolver) -> void
|
7
|
+
|
8
|
+
def absolute_type: (Types::t, context: TypeNameResolver::context) { (Types::t) -> TypeName } -> Types::t
|
9
|
+
|
10
|
+
def validate_type: (Types::t, context: TypeNameResolver::context) -> void
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,327 @@
|
|
1
|
+
class Time
|
2
|
+
interface _TimeLike
|
3
|
+
def year: () -> Integer
|
4
|
+
def mon: () -> Integer
|
5
|
+
def day: () -> Integer
|
6
|
+
end
|
7
|
+
|
8
|
+
#
|
9
|
+
# Return the number of seconds the specified time zone differs
|
10
|
+
# from UTC.
|
11
|
+
#
|
12
|
+
# Numeric time zones that include minutes, such as
|
13
|
+
# <code>-10:00</code> or <code>+1330</code> will work, as will
|
14
|
+
# simpler hour-only time zones like <code>-10</code> or
|
15
|
+
# <code>+13</code>.
|
16
|
+
#
|
17
|
+
# Textual time zones listed in ZoneOffset are also supported.
|
18
|
+
#
|
19
|
+
# If the time zone does not match any of the above, +zone_offset+
|
20
|
+
# will check if the local time zone (both with and without
|
21
|
+
# potential Daylight Saving \Time changes being in effect) matches
|
22
|
+
# +zone+. Specifying a value for +year+ will change the year used
|
23
|
+
# to find the local time zone.
|
24
|
+
#
|
25
|
+
# If +zone_offset+ is unable to determine the offset, nil will be
|
26
|
+
# returned.
|
27
|
+
#
|
28
|
+
# require 'time'
|
29
|
+
#
|
30
|
+
# Time.zone_offset("EST") #=> -18000
|
31
|
+
#
|
32
|
+
# You must require 'time' to use this method.
|
33
|
+
#
|
34
|
+
def self.zone_offset: (String zone, ?Integer year) -> Integer
|
35
|
+
|
36
|
+
#
|
37
|
+
# Takes a string representation of a Time and attempts to parse it
|
38
|
+
# using a heuristic.
|
39
|
+
#
|
40
|
+
# require 'time'
|
41
|
+
#
|
42
|
+
# Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
|
43
|
+
#
|
44
|
+
# Any missing pieces of the date are inferred based on the current date.
|
45
|
+
#
|
46
|
+
# require 'time'
|
47
|
+
#
|
48
|
+
# # assuming the current date is "2011-10-31"
|
49
|
+
# Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500
|
50
|
+
#
|
51
|
+
# We can change the date used to infer our missing elements by passing a second
|
52
|
+
# object that responds to #mon, #day and #year, such as Date, Time or DateTime.
|
53
|
+
# We can also use our own object.
|
54
|
+
#
|
55
|
+
# require 'time'
|
56
|
+
#
|
57
|
+
# class MyDate
|
58
|
+
# attr_reader :mon, :day, :year
|
59
|
+
#
|
60
|
+
# def initialize(mon, day, year)
|
61
|
+
# @mon, @day, @year = mon, day, year
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# d = Date.parse("2010-10-28")
|
66
|
+
# t = Time.parse("2010-10-29")
|
67
|
+
# dt = DateTime.parse("2010-10-30")
|
68
|
+
# md = MyDate.new(10,31,2010)
|
69
|
+
#
|
70
|
+
# Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500
|
71
|
+
# Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500
|
72
|
+
# Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500
|
73
|
+
# Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500
|
74
|
+
#
|
75
|
+
# If a block is given, the year described in +date+ is converted
|
76
|
+
# by the block. This is specifically designed for handling two
|
77
|
+
# digit years. For example, if you wanted to treat all two digit
|
78
|
+
# years prior to 70 as the year 2000+ you could write this:
|
79
|
+
#
|
80
|
+
# require 'time'
|
81
|
+
#
|
82
|
+
# Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
|
83
|
+
# #=> 2001-10-31 00:00:00 -0500
|
84
|
+
# Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)}
|
85
|
+
# #=> 1970-10-31 00:00:00 -0500
|
86
|
+
#
|
87
|
+
# If the upper components of the given time are broken or missing, they are
|
88
|
+
# supplied with those of +now+. For the lower components, the minimum
|
89
|
+
# values (1 or 0) are assumed if broken or missing. For example:
|
90
|
+
#
|
91
|
+
# require 'time'
|
92
|
+
#
|
93
|
+
# # Suppose it is "Thu Nov 29 14:33:20 2001" now and
|
94
|
+
# # your time zone is EST which is GMT-5.
|
95
|
+
# now = Time.parse("Thu Nov 29 14:33:20 2001")
|
96
|
+
# Time.parse("16:30", now) #=> 2001-11-29 16:30:00 -0500
|
97
|
+
# Time.parse("7/23", now) #=> 2001-07-23 00:00:00 -0500
|
98
|
+
# Time.parse("Aug 31", now) #=> 2001-08-31 00:00:00 -0500
|
99
|
+
# Time.parse("Aug 2000", now) #=> 2000-08-01 00:00:00 -0500
|
100
|
+
#
|
101
|
+
# Since there are numerous conflicts among locally defined time zone
|
102
|
+
# abbreviations all over the world, this method is not intended to
|
103
|
+
# understand all of them. For example, the abbreviation "CST" is
|
104
|
+
# used variously as:
|
105
|
+
#
|
106
|
+
# -06:00 in America/Chicago,
|
107
|
+
# -05:00 in America/Havana,
|
108
|
+
# +08:00 in Asia/Harbin,
|
109
|
+
# +09:30 in Australia/Darwin,
|
110
|
+
# +10:30 in Australia/Adelaide,
|
111
|
+
# etc.
|
112
|
+
#
|
113
|
+
# Based on this fact, this method only understands the time zone
|
114
|
+
# abbreviations described in RFC 822 and the system time zone, in the
|
115
|
+
# order named. (i.e. a definition in RFC 822 overrides the system
|
116
|
+
# time zone definition.) The system time zone is taken from
|
117
|
+
# <tt>Time.local(year, 1, 1).zone</tt> and
|
118
|
+
# <tt>Time.local(year, 7, 1).zone</tt>.
|
119
|
+
# If the extracted time zone abbreviation does not match any of them,
|
120
|
+
# it is ignored and the given time is regarded as a local time.
|
121
|
+
#
|
122
|
+
# ArgumentError is raised if Date._parse cannot extract information from
|
123
|
+
# +date+ or if the Time class cannot represent specified date.
|
124
|
+
#
|
125
|
+
# This method can be used as a fail-safe for other parsing methods as:
|
126
|
+
#
|
127
|
+
# Time.rfc2822(date) rescue Time.parse(date)
|
128
|
+
# Time.httpdate(date) rescue Time.parse(date)
|
129
|
+
# Time.xmlschema(date) rescue Time.parse(date)
|
130
|
+
#
|
131
|
+
# A failure of Time.parse should be checked, though.
|
132
|
+
#
|
133
|
+
# You must require 'time' to use this method.
|
134
|
+
#
|
135
|
+
def self.parse: (String date, ?_TimeLike now) ?{ (Integer) -> Integer } -> Time
|
136
|
+
|
137
|
+
#
|
138
|
+
# Works similar to +parse+ except that instead of using a
|
139
|
+
# heuristic to detect the format of the input string, you provide
|
140
|
+
# a second argument that describes the format of the string.
|
141
|
+
#
|
142
|
+
# If a block is given, the year described in +date+ is converted by the
|
143
|
+
# block. For example:
|
144
|
+
#
|
145
|
+
# Time.strptime(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
|
146
|
+
#
|
147
|
+
# Below is a list of the formatting options:
|
148
|
+
#
|
149
|
+
# %a :: The abbreviated weekday name ("Sun")
|
150
|
+
# %A :: The full weekday name ("Sunday")
|
151
|
+
# %b :: The abbreviated month name ("Jan")
|
152
|
+
# %B :: The full month name ("January")
|
153
|
+
# %c :: The preferred local date and time representation
|
154
|
+
# %C :: Century (20 in 2009)
|
155
|
+
# %d :: Day of the month (01..31)
|
156
|
+
# %D :: Date (%m/%d/%y)
|
157
|
+
# %e :: Day of the month, blank-padded ( 1..31)
|
158
|
+
# %F :: Equivalent to %Y-%m-%d (the ISO 8601 date format)
|
159
|
+
# %g :: The last two digits of the commercial year
|
160
|
+
# %G :: The week-based year according to ISO-8601 (week 1 starts on Monday
|
161
|
+
# and includes January 4)
|
162
|
+
# %h :: Equivalent to %b
|
163
|
+
# %H :: Hour of the day, 24-hour clock (00..23)
|
164
|
+
# %I :: Hour of the day, 12-hour clock (01..12)
|
165
|
+
# %j :: Day of the year (001..366)
|
166
|
+
# %k :: hour, 24-hour clock, blank-padded ( 0..23)
|
167
|
+
# %l :: hour, 12-hour clock, blank-padded ( 0..12)
|
168
|
+
# %L :: Millisecond of the second (000..999)
|
169
|
+
# %m :: Month of the year (01..12)
|
170
|
+
# %M :: Minute of the hour (00..59)
|
171
|
+
# %n :: Newline (\n)
|
172
|
+
# %N :: Fractional seconds digits
|
173
|
+
# %p :: Meridian indicator ("AM" or "PM")
|
174
|
+
# %P :: Meridian indicator ("am" or "pm")
|
175
|
+
# %r :: time, 12-hour (same as %I:%M:%S %p)
|
176
|
+
# %R :: time, 24-hour (%H:%M)
|
177
|
+
# %s :: Number of seconds since 1970-01-01 00:00:00 UTC.
|
178
|
+
# %S :: Second of the minute (00..60)
|
179
|
+
# %t :: Tab character (\t)
|
180
|
+
# %T :: time, 24-hour (%H:%M:%S)
|
181
|
+
# %u :: Day of the week as a decimal, Monday being 1. (1..7)
|
182
|
+
# %U :: Week number of the current year, starting with the first Sunday as
|
183
|
+
# the first day of the first week (00..53)
|
184
|
+
# %v :: VMS date (%e-%b-%Y)
|
185
|
+
# %V :: Week number of year according to ISO 8601 (01..53)
|
186
|
+
# %W :: Week number of the current year, starting with the first Monday
|
187
|
+
# as the first day of the first week (00..53)
|
188
|
+
# %w :: Day of the week (Sunday is 0, 0..6)
|
189
|
+
# %x :: Preferred representation for the date alone, no time
|
190
|
+
# %X :: Preferred representation for the time alone, no date
|
191
|
+
# %y :: Year without a century (00..99)
|
192
|
+
# %Y :: Year which may include century, if provided
|
193
|
+
# %z :: Time zone as hour offset from UTC (e.g. +0900)
|
194
|
+
# %Z :: Time zone name
|
195
|
+
# %% :: Literal "%" character
|
196
|
+
# %+ :: date(1) (%a %b %e %H:%M:%S %Z %Y)
|
197
|
+
#
|
198
|
+
# require 'time'
|
199
|
+
#
|
200
|
+
# Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500
|
201
|
+
#
|
202
|
+
# You must require 'time' to use this method.
|
203
|
+
#
|
204
|
+
def self.strptime: (String date, String format, ?_TimeLike now) ?{ (Integer) -> Integer } -> Time
|
205
|
+
|
206
|
+
#
|
207
|
+
# Parses +date+ as date-time defined by RFC 2822 and converts it to a Time
|
208
|
+
# object. The format is identical to the date format defined by RFC 822 and
|
209
|
+
# updated by RFC 1123.
|
210
|
+
#
|
211
|
+
# ArgumentError is raised if +date+ is not compliant with RFC 2822
|
212
|
+
# or if the Time class cannot represent specified date.
|
213
|
+
#
|
214
|
+
# See #rfc2822 for more information on this format.
|
215
|
+
#
|
216
|
+
# require 'time'
|
217
|
+
#
|
218
|
+
# Time.rfc2822("Wed, 05 Oct 2011 22:26:12 -0400")
|
219
|
+
# #=> 2010-10-05 22:26:12 -0400
|
220
|
+
#
|
221
|
+
# You must require 'time' to use this method.
|
222
|
+
#
|
223
|
+
def self.rfc2822: (String date) -> Time
|
224
|
+
|
225
|
+
alias self.rfc822 self.rfc2822
|
226
|
+
|
227
|
+
#
|
228
|
+
# Parses +date+ as an HTTP-date defined by RFC 2616 and converts it to a
|
229
|
+
# Time object.
|
230
|
+
#
|
231
|
+
# ArgumentError is raised if +date+ is not compliant with RFC 2616 or if
|
232
|
+
# the Time class cannot represent specified date.
|
233
|
+
#
|
234
|
+
# See #httpdate for more information on this format.
|
235
|
+
#
|
236
|
+
# require 'time'
|
237
|
+
#
|
238
|
+
# Time.httpdate("Thu, 06 Oct 2011 02:26:12 GMT")
|
239
|
+
# #=> 2011-10-06 02:26:12 UTC
|
240
|
+
#
|
241
|
+
# You must require 'time' to use this method.
|
242
|
+
#
|
243
|
+
def self.httpdate: (String date) -> Time
|
244
|
+
|
245
|
+
#
|
246
|
+
# Parses +date+ as a dateTime defined by the XML Schema and converts it to
|
247
|
+
# a Time object. The format is a restricted version of the format defined
|
248
|
+
# by ISO 8601.
|
249
|
+
#
|
250
|
+
# ArgumentError is raised if +date+ is not compliant with the format or if
|
251
|
+
# the Time class cannot represent specified date.
|
252
|
+
#
|
253
|
+
# See #xmlschema for more information on this format.
|
254
|
+
#
|
255
|
+
# require 'time'
|
256
|
+
#
|
257
|
+
# Time.xmlschema("2011-10-05T22:26:12-04:00")
|
258
|
+
# #=> 2011-10-05 22:26:12-04:00
|
259
|
+
#
|
260
|
+
# You must require 'time' to use this method.
|
261
|
+
#
|
262
|
+
def self.xmlschema: (String date) -> Time
|
263
|
+
|
264
|
+
alias self.iso8601 self.xmlschema
|
265
|
+
|
266
|
+
#
|
267
|
+
# Returns a string which represents the time as date-time defined by RFC 2822:
|
268
|
+
#
|
269
|
+
# day-of-week, DD month-name CCYY hh:mm:ss zone
|
270
|
+
#
|
271
|
+
# where zone is [+-]hhmm.
|
272
|
+
#
|
273
|
+
# If +self+ is a UTC time, -0000 is used as zone.
|
274
|
+
#
|
275
|
+
# require 'time'
|
276
|
+
#
|
277
|
+
# t = Time.now
|
278
|
+
# t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400"
|
279
|
+
#
|
280
|
+
# You must require 'time' to use this method.
|
281
|
+
#
|
282
|
+
def rfc2822: () -> String
|
283
|
+
|
284
|
+
alias rfc822 rfc2822
|
285
|
+
|
286
|
+
#
|
287
|
+
# Returns a string which represents the time as RFC 1123 date of HTTP-date
|
288
|
+
# defined by RFC 2616:
|
289
|
+
#
|
290
|
+
# day-of-week, DD month-name CCYY hh:mm:ss GMT
|
291
|
+
#
|
292
|
+
# Note that the result is always UTC (GMT).
|
293
|
+
#
|
294
|
+
# require 'time'
|
295
|
+
#
|
296
|
+
# t = Time.now
|
297
|
+
# t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
|
298
|
+
#
|
299
|
+
# You must require 'time' to use this method.
|
300
|
+
#
|
301
|
+
def httpdate: () -> String
|
302
|
+
|
303
|
+
#
|
304
|
+
# Returns a string which represents the time as a dateTime defined by XML
|
305
|
+
# Schema:
|
306
|
+
#
|
307
|
+
# CCYY-MM-DDThh:mm:ssTZD
|
308
|
+
# CCYY-MM-DDThh:mm:ss.sssTZD
|
309
|
+
#
|
310
|
+
# where TZD is Z or [+-]hh:mm.
|
311
|
+
#
|
312
|
+
# If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
|
313
|
+
#
|
314
|
+
# +fractional_digits+ specifies a number of digits to use for fractional
|
315
|
+
# seconds. Its default value is 0.
|
316
|
+
#
|
317
|
+
# require 'time'
|
318
|
+
#
|
319
|
+
# t = Time.now
|
320
|
+
# t.iso8601 # => "2011-10-05T22:26:12-04:00"
|
321
|
+
#
|
322
|
+
# You must require 'time' to use this method.
|
323
|
+
#
|
324
|
+
def xmlschema: (?Integer fraction_digits) -> String
|
325
|
+
|
326
|
+
alias iso8601 xmlschema
|
327
|
+
end
|