incomplete_date 0.1.2
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +22 -0
- data/lib/incomplete_date.rb +296 -0
- data/lib/incomplete_date/active_record.rb +55 -0
- data/lib/incomplete_date/date.rb +22 -0
- data/lib/incomplete_date/form_builder.rb +14 -0
- data/lib/incomplete_date/version.rb +3 -0
- data/lib/tasks/incomplete_date_tasks.rake +4 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 60bcab9d810f4b939ecf3b9ff1e5df23f8b04482947110dedd527766df9d6fb3
|
4
|
+
data.tar.gz: 0a271f6433f699854bf2939ad1eb5d46cdbab7783430554185e1bedcf3090a31
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a725a7381bb110165ce22e002e62c616a7d95155c5fdd14f7f5e7b44212e0909266081ae59b1b51c04337e7175c5aea67703b8360a1a259eddabbfd81a050f1b
|
7
|
+
data.tar.gz: 7e7fd53527085104b73e7dba177a32d9bf22f597c23e4095e7109c089b194435623f0ba3f27b1945e771cd4d11419ebe1b7b003163dae831b4ac512f7496173f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Ernesto García
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the incomplete_date plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the incomplete_date plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'IncompleteDate'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require 'incomplete_date/date'
|
2
|
+
require 'incomplete_date/active_record'
|
3
|
+
require 'incomplete_date/form_builder'
|
4
|
+
|
5
|
+
class IncompleteDate
|
6
|
+
attr_reader :day, :month, :year
|
7
|
+
attr_accessor :circa
|
8
|
+
alias mday day
|
9
|
+
|
10
|
+
def initialize(value)
|
11
|
+
@circa = false
|
12
|
+
|
13
|
+
case value
|
14
|
+
when Integer
|
15
|
+
@circa = (value < 0)
|
16
|
+
num = value.abs
|
17
|
+
num, @day = num.divmod(100)
|
18
|
+
@year, @month = num.divmod(100)
|
19
|
+
when Hash
|
20
|
+
@day, @month, @year = value[:day], value[:month], value[:year]
|
21
|
+
@circa = value.fetch(:circa, false)
|
22
|
+
when Date
|
23
|
+
@day, @month, @year = value.mday, value.month, value.year
|
24
|
+
when IncompleteDate
|
25
|
+
@day, @month, @year, @circa = value.day, value.month, value.year, value.circa
|
26
|
+
when nil #invaluable for existing databases!
|
27
|
+
@day, @month, @year, @circa = 0, 0, 0, false
|
28
|
+
else
|
29
|
+
raise ArgumentError, "Invalid #{self.class.name} specification"
|
30
|
+
end
|
31
|
+
|
32
|
+
@day = nil if @day == 0
|
33
|
+
@month = nil if @month == 0
|
34
|
+
@year = nil if @year == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
#--
|
38
|
+
# Core attributes handling
|
39
|
+
#++
|
40
|
+
|
41
|
+
#
|
42
|
+
# Returns +true+ if the given year is a leap year, +false+ otherwise.
|
43
|
+
#
|
44
|
+
def self.leap_year?(year)
|
45
|
+
raise ArgumentError, "year cannot be null or zero" if year.nil? or year.zero?
|
46
|
+
(year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.max_month_days(month = nil, year = nil)
|
50
|
+
year ||= 2000 # Assume a leap year if year is not known
|
51
|
+
case month
|
52
|
+
when nil,1,3,5,7,8,10,12 then 31
|
53
|
+
when 4,6,9,11 then 30
|
54
|
+
when 2 then leap_year?(year) ? 29 : 28
|
55
|
+
else raise ArgumentError, "invalid month"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid_day?(day, month = nil, year = nil)
|
60
|
+
return true if day.nil? || day.zero?
|
61
|
+
max = IncompleteDate.max_month_days(month || self.month, year || self.year)
|
62
|
+
(1..max).include?(day)
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_month?(month)
|
66
|
+
return true if month.nil? || month.zero?
|
67
|
+
(1..12).include?(month) && valid_day?(self.day, month)
|
68
|
+
end
|
69
|
+
|
70
|
+
def valid_year?(year, month = nil, day = nil)
|
71
|
+
return true if year.nil? || year.zero?
|
72
|
+
day ||= self.day
|
73
|
+
month ||= self.month
|
74
|
+
!(!IncompleteDate.leap_year?(year) && (day == 29) && (month == 2))
|
75
|
+
end
|
76
|
+
|
77
|
+
def day=(value)
|
78
|
+
value = (value == 0) ? nil : value
|
79
|
+
raise ArgumentError, "invalid day" unless valid_day?(value)
|
80
|
+
@day = value
|
81
|
+
end
|
82
|
+
|
83
|
+
def month=(value)
|
84
|
+
value = (value == 0) ? nil : value
|
85
|
+
raise ArgumentError, "invalid month" unless valid_month?(value)
|
86
|
+
@month = value
|
87
|
+
end
|
88
|
+
|
89
|
+
def year=(value)
|
90
|
+
value = (value == 0) ? nil : value
|
91
|
+
raise ArgumentError, "invalid year" unless valid_year?(value)
|
92
|
+
@year = value
|
93
|
+
end
|
94
|
+
|
95
|
+
def circa?
|
96
|
+
@circa
|
97
|
+
end
|
98
|
+
|
99
|
+
VALID_DATE_PARTS = [:year, :month, :day, :circa]
|
100
|
+
|
101
|
+
def [](part_name)
|
102
|
+
raise ArgumentError, "Invalid date part #{part_name}" unless VALID_DATE_PARTS.include?(part_name)
|
103
|
+
self.send(part_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def []=(part_name, value)
|
107
|
+
raise ArgumentError, "Invalid date part #{part_name}" unless VALID_DATE_PARTS.include?(part_name)
|
108
|
+
self.send("#{part_name}=", value)
|
109
|
+
end
|
110
|
+
|
111
|
+
#--
|
112
|
+
# Testing completeness
|
113
|
+
#++
|
114
|
+
|
115
|
+
def incomplete?
|
116
|
+
@day.nil? || @month.nil? || @year.nil?
|
117
|
+
end
|
118
|
+
|
119
|
+
def complete?
|
120
|
+
!incomplete?
|
121
|
+
end
|
122
|
+
|
123
|
+
def exact?
|
124
|
+
complete? && !circa?
|
125
|
+
end
|
126
|
+
|
127
|
+
def empty?
|
128
|
+
@day.nil? && @month.nil? && @year.nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
def has?(*parts)
|
132
|
+
parts.collect!(&:to_sym)
|
133
|
+
parts.inject(true) { |total,part| total && !self.send(part).nil? }
|
134
|
+
end
|
135
|
+
|
136
|
+
def has_day?
|
137
|
+
!@day.nil?
|
138
|
+
end
|
139
|
+
|
140
|
+
def has_month?
|
141
|
+
!@month.nil?
|
142
|
+
end
|
143
|
+
|
144
|
+
def has_year?
|
145
|
+
!@year.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
def defines_birthday?
|
149
|
+
has_day? && has_month?
|
150
|
+
end
|
151
|
+
|
152
|
+
def defined_parts
|
153
|
+
VALID_DATE_PARTS.reject { |part| (part == :circa) || self[part].nil? }
|
154
|
+
end
|
155
|
+
|
156
|
+
#++
|
157
|
+
# Relation to complete dates
|
158
|
+
#--
|
159
|
+
|
160
|
+
#
|
161
|
+
# Returns +true+ if the given date is included in the possible set of complete
|
162
|
+
# dates that match this incomplete date.
|
163
|
+
#
|
164
|
+
# For instance 2003-xx-xx includes 2003-12-24 (or any date within the year
|
165
|
+
# 2003) but it does not include 1999-12-14, for instance.
|
166
|
+
#
|
167
|
+
# The argument can be either a Date instance or an IncompleteDate instance.
|
168
|
+
#
|
169
|
+
def include?(date)
|
170
|
+
(self.year.nil? || (date.year == self.year)) &&
|
171
|
+
(self.month.nil? || (date.month == self.month)) &&
|
172
|
+
(self.day.nil? || (date.mday == self.mday))
|
173
|
+
end
|
174
|
+
|
175
|
+
#
|
176
|
+
# Returns the lowest possible date that matches this incomplete date.
|
177
|
+
#
|
178
|
+
# Only defined if this incomplete date has the year part defined. Otherwise it
|
179
|
+
# returns +nil+.
|
180
|
+
#
|
181
|
+
# see #highest
|
182
|
+
#
|
183
|
+
def lowest
|
184
|
+
return nil unless has_year?
|
185
|
+
Date.civil(self.year, self.month || 1, self.day || 1)
|
186
|
+
end
|
187
|
+
alias min lowest
|
188
|
+
alias first lowest
|
189
|
+
|
190
|
+
#
|
191
|
+
# Returns the highest possible date that matches this incomplete date.
|
192
|
+
#
|
193
|
+
# Only defined if this incomplete date has the year part defined. Otherwise it
|
194
|
+
# returns +nil+.
|
195
|
+
#
|
196
|
+
# see #lowest
|
197
|
+
#
|
198
|
+
def highest
|
199
|
+
return nil unless has_year?
|
200
|
+
max_month = self.month || 12
|
201
|
+
max_day = self.day || IncompleteDate.max_month_days(max_month, self.year)
|
202
|
+
Date.civil(self.year, max_month, max_day)
|
203
|
+
end
|
204
|
+
alias max highest
|
205
|
+
alias last highest
|
206
|
+
|
207
|
+
#--
|
208
|
+
# Conversions
|
209
|
+
#++
|
210
|
+
|
211
|
+
#
|
212
|
+
# Returns an incomplete date which only has the birthday parts (month and day)
|
213
|
+
# taken from this incomplete date. If the needed date parts are not defined,
|
214
|
+
# it returns +nil+.
|
215
|
+
#
|
216
|
+
def to_birthday
|
217
|
+
return nil unless defines_birthday?
|
218
|
+
IncompleteDate.new(:month => month, :day => day)
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
# Converts this incomplete date to a standard date value. Any missing date
|
223
|
+
# parts can be provided by the hash argument, or else are taken from today's
|
224
|
+
# date, or a reference date that be given as an optional argument with key
|
225
|
+
# +:ref+. In the case of the day missing and not explicitely provided, it
|
226
|
+
# defaults to 1, and not to the reference date.
|
227
|
+
#
|
228
|
+
def to_date(opts = {})
|
229
|
+
ref = opts.fetch(:ref, Date.today)
|
230
|
+
Date.civil(
|
231
|
+
(self.year || opts[:year] || ref.year).to_i,
|
232
|
+
(self.month || opts[:month] || ref.month).to_i,
|
233
|
+
(self.day || opts[:day] || 1).to_i)
|
234
|
+
end
|
235
|
+
|
236
|
+
def to_incomplete_date
|
237
|
+
self
|
238
|
+
end
|
239
|
+
|
240
|
+
#
|
241
|
+
# Converts this incomplete date to its equivalent integer representation
|
242
|
+
# suitable for the database layer.
|
243
|
+
#
|
244
|
+
# The two less significant digits in the decimal representation of the number
|
245
|
+
# are the day of the month. The next two less significant digits represent the
|
246
|
+
# month (numbered from 01 to 12) and the rest of the digits represent the
|
247
|
+
# year. In any case a value of zero means that that particular part of the
|
248
|
+
# date is not known. Finally, the sign of the number represents wether the
|
249
|
+
# date is considered to be uncertain (negative) or certain (positive).
|
250
|
+
#
|
251
|
+
# This representation relies on the fact there was no year 0 in the Gregorian
|
252
|
+
# or Julian calendars (see http://en.wikipedia.org/wiki/Year_zero).
|
253
|
+
#
|
254
|
+
# The integer value zero represents a date that is completely unknown, so it
|
255
|
+
# is somehow equivalent to +nil+ in terms of meaning, and it is questionable
|
256
|
+
# that we allow instances of this class with such a configuration.
|
257
|
+
#
|
258
|
+
def to_i
|
259
|
+
y,m,d = [year,month,day].collect(&:to_i) # converts +nil+ values to zero
|
260
|
+
(circa ? -1 : 1) * (d + m*100 + y*10000)
|
261
|
+
end
|
262
|
+
|
263
|
+
def to_s
|
264
|
+
dt = to_date
|
265
|
+
ord = has_day? ? dt.day.ordinalize : nil
|
266
|
+
result = case defined_parts
|
267
|
+
when [:year, :month, :day] then dt.strftime("%B #{ord}, %Y")
|
268
|
+
when [:year, :month] then dt.strftime("%B %Y")
|
269
|
+
when [:month, :day] then dt.strftime("%B #{ord}")
|
270
|
+
when [:year, :day] then dt.strftime("#{ord} of the month, %Y")
|
271
|
+
when [:year] then dt.strftime("%Y")
|
272
|
+
when [:month] then dt.strftime("%B")
|
273
|
+
when [:day] then "#{ord} of the month"
|
274
|
+
else return "unknown"
|
275
|
+
end
|
276
|
+
circa ? "c. #{result}" : result
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
# Returns the range of dates that are included or match with this incomplete
|
281
|
+
# date.
|
282
|
+
#
|
283
|
+
# Uses #lowest and #highest to determine the extremes of the range. Returns
|
284
|
+
# +nil+ if the year is not defined.
|
285
|
+
#
|
286
|
+
def to_range
|
287
|
+
has_year? ? (min..max) : nil
|
288
|
+
end
|
289
|
+
|
290
|
+
def to_hash
|
291
|
+
result = {}
|
292
|
+
VALID_DATE_PARTS.each { |part| result[part] = self.send(part) }
|
293
|
+
result
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class IncompleteDate
|
2
|
+
module IncompleteDateAttr
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
#
|
5
|
+
# Defines a new IncompleteDate virtual attribute with name +attr_name+
|
6
|
+
# corresponding to a real integer attribute named +raw_name+ that holds the
|
7
|
+
# raw date value in the database.
|
8
|
+
#
|
9
|
+
class_methods do
|
10
|
+
|
11
|
+
def incomplete_date_attr(attr_name, raw_name)
|
12
|
+
instance_var = "@#{attr_name}"
|
13
|
+
|
14
|
+
# getter
|
15
|
+
define_method "#{attr_name}" do
|
16
|
+
value = instance_variable_get(instance_var)
|
17
|
+
value ||= IncompleteDate.new(read_attribute(raw_name))
|
18
|
+
instance_variable_set(instance_var, value)
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
# setter
|
23
|
+
define_method "#{attr_name}=" do |value|
|
24
|
+
#begin
|
25
|
+
value = IncompleteDate.new(value)
|
26
|
+
instance_variable_set(instance_var, value)
|
27
|
+
write_attribute(raw_name, value.to_i)
|
28
|
+
#rescue ArgumentError
|
29
|
+
# errors.add(raw_name)
|
30
|
+
#end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Defines several virtual attributes at once for raw real attributes
|
36
|
+
#
|
37
|
+
def incomplete_date_attrs(*names)
|
38
|
+
options = names.extract_options!
|
39
|
+
prefix = options.fetch(:prefix, 'raw')
|
40
|
+
names.each do |name|
|
41
|
+
raw_name = "#{prefix}_#{name}"
|
42
|
+
incomplete_date_attr name, raw_name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ApplicationRecord < ActiveRecord::Base
|
52
|
+
include IncompleteDate::IncompleteDateAttr
|
53
|
+
|
54
|
+
self.abstract_class = true
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Date
|
2
|
+
def circa
|
3
|
+
false
|
4
|
+
end
|
5
|
+
alias circa? circa
|
6
|
+
|
7
|
+
def to_birthday
|
8
|
+
IncompleteDate.new(:month => month, :day => day)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_i
|
12
|
+
year*10000 + month*100 + day
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_incomplete_date
|
16
|
+
IncompleteDate.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(incomplete_date)
|
20
|
+
incomplete_date.include?(self)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActionView::Helpers
|
2
|
+
class FormBuilder
|
3
|
+
def incomplete_date_select(method, options = {}, html_options = {})
|
4
|
+
date = @object.send(method) || (Date.today - 50.years)
|
5
|
+
date = date.to_incomplete_date
|
6
|
+
options.merge!(:prefix => @object_name, :include_blank => true)
|
7
|
+
# TODO: The +year+ and +circa+ tags don't have the standard +id+ according to its names.
|
8
|
+
@template.text_field_tag("#{@object_name}[#{method}][year]", date.year, :size => 5, :maxlength => 4) + ' ' +
|
9
|
+
@template.select_month(date, options.merge(:field_name => "#{method}][month")) + ' ' +
|
10
|
+
@template.select_day(date, options.merge(:field_name => "#{method}][day")) + ' ' +
|
11
|
+
@template.check_box_tag("#{@object_name}[#{method}][circa]", '1', date.circa) + ' circa'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: incomplete_date
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- gnapse
|
8
|
+
- ErCollao
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-05-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: sqlite3
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.3.6
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 1.3.6
|
42
|
+
description: This plugin creates a Value Object class that controls the logic of incomplete
|
43
|
+
dates. It also creates a class method incomplete_date_attr to hook onto Active Record
|
44
|
+
objects, so some of the attributes are stored in the database as an integer instead
|
45
|
+
of a date
|
46
|
+
email:
|
47
|
+
- gnapse@gmail.com
|
48
|
+
- daniel@collado-ruiz.es
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- MIT-LICENSE
|
54
|
+
- Rakefile
|
55
|
+
- lib/incomplete_date.rb
|
56
|
+
- lib/incomplete_date/active_record.rb
|
57
|
+
- lib/incomplete_date/date.rb
|
58
|
+
- lib/incomplete_date/form_builder.rb
|
59
|
+
- lib/incomplete_date/version.rb
|
60
|
+
- lib/tasks/incomplete_date_tasks.rake
|
61
|
+
homepage: https://github.com/gnapse/incomplete_date
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubygems_version: 3.0.1
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: This plugin allows a Rails application to store and manage incomplete date
|
84
|
+
data, which is very common in historical archives, particularly in genealogy.
|
85
|
+
test_files: []
|