fuzzy-date 0.1.5 → 0.1.6
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/lib/fuzzy-date.rb +2 -22
- data/lib/fuzzy-date/analyze.rb +166 -0
- data/lib/fuzzy-date/fuzzy-date.rb +1 -142
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be67faf3dd4b030851460dba616f21e3cf0ba8da
|
4
|
+
data.tar.gz: c865e0ef0a86ea0feef6c54138f487974e56056d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e7f5a0a1998319549eedcadd8c4fb22b394b08121d0fe7d3eb877517d7aa41cdf51acbfb2a30b92198d9bdd4f40118c9d4a2322978afd58355a53724cf44137
|
7
|
+
data.tar.gz: 1f36b09a16547b6c13cf44b3da1a3b570739f3b58644b5b5f5d58af7acc13e643952280a3d37569ee3f3fafba963a13dac3eb892f3ffd64d8284ae06aefd869c
|
data/lib/fuzzy-date.rb
CHANGED
@@ -1,29 +1,9 @@
|
|
1
|
-
|
1
|
+
require 'fuzzy-date/analyze'
|
2
2
|
require 'fuzzy-date/variables'
|
3
3
|
require 'fuzzy-date/fuzzy-date'
|
4
4
|
|
5
5
|
class FuzzyDate
|
6
|
-
VERSION = '0.1.
|
7
|
-
|
8
|
-
# *Note*: This is only for single dates - not ranges.
|
9
|
-
#
|
10
|
-
# Possible incoming date formats:
|
11
|
-
# * YYYY-MM-DD - starts with 3 or 4 digit year, and month and day may be 1 or 2 digits
|
12
|
-
# * YYYY-MM - 3 or 4 digit year, then 1 or 2 digit month
|
13
|
-
# * YYYY - 3 or 4 digit year
|
14
|
-
# * MM-DD-YYYY - 1 or 2 digit month, then 1 or 2 digit day, then 1 to 4 digit year
|
15
|
-
# * DD-MM-YYYY - 1 or 2 digit day, then 1 or 2 digit month, then 1 to 4 digit year if euro is true
|
16
|
-
# * MM-YYYY - 1 or 2 digit month, then 1 to 4 digit year
|
17
|
-
# * DD-MMM - 1 or 2 digit day, then month name or abbreviation
|
18
|
-
# * DD-MMM-YYYY - 1 or 2 digit day, then month name or abbreviation, then 1 to 4 digit year
|
19
|
-
# * MMM-YYYY - month name or abbreviation, then 1 to 4 digit year
|
20
|
-
# * MMM-DD-YYYY - month name or abbreviation, then 1 or 2 digit day, then 1 to 4 digit year
|
21
|
-
#
|
22
|
-
# Notes:
|
23
|
-
# - Commas are optional.
|
24
|
-
# - Delimiters can be most anything non-alphanumeric.
|
25
|
-
# - All dates may be suffixed with the era (AD, BC, CE, BCE). AD is assumed.
|
26
|
-
# - Dates may be prefixed by circa words (Circa, About, Abt).
|
6
|
+
VERSION = '0.1.6'
|
27
7
|
|
28
8
|
def self.parse( date, euro = false )
|
29
9
|
fuzzy_date = FuzzyDate.new date, euro
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class FuzzyDate
|
4
|
+
|
5
|
+
# *Note*: This is only for single dates - not ranges.
|
6
|
+
#
|
7
|
+
# Possible incoming date formats:
|
8
|
+
# * YYYY-MM-DD - starts with 3 or 4 digit year, and month and day may be 1 or 2 digits
|
9
|
+
# * YYYY-MM - 3 or 4 digit year, then 1 or 2 digit month
|
10
|
+
# * YYYY - 3 or 4 digit year
|
11
|
+
# * MM-DD-YYYY - 1 or 2 digit month, then 1 or 2 digit day, then 1 to 4 digit year
|
12
|
+
# * DD-MM-YYYY - 1 or 2 digit day, then 1 or 2 digit month, then 1 to 4 digit year if euro is true
|
13
|
+
# * MM-YYYY - 1 or 2 digit month, then 1 to 4 digit year
|
14
|
+
# * DD-MMM - 1 or 2 digit day, then month name or abbreviation
|
15
|
+
# * DD-MMM-YYYY - 1 or 2 digit day, then month name or abbreviation, then 1 to 4 digit year
|
16
|
+
# * MMM-YYYY - month name or abbreviation, then 1 to 4 digit year
|
17
|
+
# * MMM-DD-YYYY - month name or abbreviation, then 1 or 2 digit day, then 1 to 4 digit year
|
18
|
+
#
|
19
|
+
# Notes:
|
20
|
+
# - Commas are optional.
|
21
|
+
# - Delimiters can be most anything non-alphanumeric.
|
22
|
+
# - All dates may be suffixed with the era (AD, BC, CE, BCE). AD is assumed.
|
23
|
+
# - Dates may be prefixed by circa words (Circa, About, Abt).
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def analyze( date, euro )
|
28
|
+
|
29
|
+
date = clean_parameter date
|
30
|
+
|
31
|
+
@date_parts[ :original ] = date
|
32
|
+
|
33
|
+
date = massage date
|
34
|
+
@date_parts[ :fixed ] = date
|
35
|
+
|
36
|
+
#- Takes care of YYYY
|
37
|
+
if date =~ /^(\d{1,4})$/
|
38
|
+
year = $1.to_i.to_s
|
39
|
+
month = nil
|
40
|
+
day = nil
|
41
|
+
|
42
|
+
#- Takes care of YYYY-MM-DD and YYYY-MM
|
43
|
+
elsif date =~ /^(\d{3,4})(?:-(\d{1,2})(?:-(\d{1,2}))?)?$/
|
44
|
+
year = $1.to_i.to_s
|
45
|
+
month = $2 ? $2.to_i.to_s : nil
|
46
|
+
day = $3 ? $3.to_i.to_s : nil
|
47
|
+
|
48
|
+
#- Takes care of DD-MM-YYYY
|
49
|
+
elsif date =~ /^(\d{1,2})-(\d{1,2})-(\d{1,4})$/ and euro
|
50
|
+
day = $1.to_i.to_s
|
51
|
+
month = $2.to_i.to_s
|
52
|
+
year = $3.to_i.to_s
|
53
|
+
|
54
|
+
#- Takes care of MM-DD-YYYY
|
55
|
+
elsif date =~ /^(\d{1,2})-(\d{1,2})-(\d{1,4})$/
|
56
|
+
month = $1.to_i.to_s
|
57
|
+
day = $2.to_i.to_s
|
58
|
+
year = $3.to_i.to_s
|
59
|
+
|
60
|
+
#- Takes care of MM-YYYY
|
61
|
+
elsif date =~ /^(\d{1,2})-(\d{1,4})?$/
|
62
|
+
month = $1.to_i.to_s
|
63
|
+
day = nil
|
64
|
+
year = $2.to_i.to_s
|
65
|
+
|
66
|
+
#- Takes care of DD-MMM-YYYY and DD-MMM
|
67
|
+
elsif date =~ /^(\d{1,2})(?:-(#{ @month_abbreviations.keys.join( '|' ) }).*?(?:-(\d{1,4}))?)?$/i
|
68
|
+
month_text = $2.to_s.capitalize
|
69
|
+
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
70
|
+
day = $1.to_i.to_s
|
71
|
+
year = $3 ? $3.to_i.to_s : nil
|
72
|
+
|
73
|
+
#- Takes care of MMM-DD-YYYY
|
74
|
+
elsif date =~ /^(#{ @month_abbreviations.keys.join( '|' ) }).*?-(\d{1,2})-(\d{1,4})$/i
|
75
|
+
month_text = $1.to_s.capitalize
|
76
|
+
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
77
|
+
day = $2.to_i.to_s
|
78
|
+
year = $3 ? $3.to_i.to_s : nil
|
79
|
+
|
80
|
+
#- Takes care of MMM-YYYY and MMM
|
81
|
+
elsif date =~ /^(#{ @month_abbreviations.keys.join( '|' ) }).*?(?:-(\d{1,4}))?$/i
|
82
|
+
month_text = $1.to_s.capitalize
|
83
|
+
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
84
|
+
day = nil
|
85
|
+
year = $2 ? $2.to_i.to_s : nil
|
86
|
+
|
87
|
+
else
|
88
|
+
raise ArgumentError.new( 'Cannot parse date.' )
|
89
|
+
end
|
90
|
+
|
91
|
+
@date_parts[ :year ] = year ? year.to_i : nil
|
92
|
+
@date_parts[ :month ] = month ? month.to_i : nil
|
93
|
+
@date_parts[ :day ] = day ? day.to_i : nil
|
94
|
+
#return { :circa => "day: #{ day }, month: #{ month }, year: #{ year }" }
|
95
|
+
|
96
|
+
#- Some error checking at this point
|
97
|
+
if month.to_i > 13
|
98
|
+
raise ArgumentError.new( 'Month cannot be greater than 12.' )
|
99
|
+
elsif month and day and day.to_i > @days_in_month[ month.to_i ]
|
100
|
+
unless month.to_i == 2 and year and Date.parse( '1/1/' + year ).leap? and day.to_i == 29
|
101
|
+
raise ArgumentError.new( 'Too many days in this month.' )
|
102
|
+
end
|
103
|
+
elsif month and month.to_i < 1
|
104
|
+
raise ArgumentError.new( 'Month cannot be less than 1.' )
|
105
|
+
elsif day and day.to_i < 1
|
106
|
+
raise ArgumentError.new( 'Day cannot be less than 1.' )
|
107
|
+
end
|
108
|
+
|
109
|
+
month_name = @month_names[ month.to_i ]
|
110
|
+
@date_parts[ :month_name ] = month_name
|
111
|
+
|
112
|
+
# ----------------------------------------------------------------------
|
113
|
+
|
114
|
+
show_era = ' ' + @date_parts[ :era ]
|
115
|
+
show_circa = @date_parts[ :circa ] == true ? 'About ' : ''
|
116
|
+
|
117
|
+
if year and month and day
|
118
|
+
@date_parts[ :short ] = show_circa + month + '/' + day + '/' + year + show_era
|
119
|
+
@date_parts[ :long ] = show_circa + month_name + ' ' + day + ', ' + year + show_era
|
120
|
+
modified_long = show_circa + month_name + ' ' + day + ', ' + year.rjust( 4, "0" ) + show_era
|
121
|
+
@date_parts[ :full ] = show_circa + Date.parse( modified_long ).strftime( '%A,' ) + Date.parse( day + ' ' + month_name + ' ' + year.rjust( 4, "0" ) ).strftime( ' %B %-1d, %Y' ) + show_era
|
122
|
+
elsif year and month
|
123
|
+
@date_parts[ :short ] = show_circa + month + '/' + year + show_era
|
124
|
+
@date_parts[ :long ] = show_circa + month_name + ', ' + year + show_era
|
125
|
+
@date_parts[ :full ] = @date_parts[ :long ]
|
126
|
+
elsif month and day
|
127
|
+
month_text = @month_abbreviations.key(month_text) || month_text
|
128
|
+
@date_parts[ :short ] = show_circa + day + '-' + month_text
|
129
|
+
@date_parts[ :long ] = show_circa + day + ' ' + month_name
|
130
|
+
@date_parts[ :full ] = @date_parts[ :long ]
|
131
|
+
elsif year
|
132
|
+
@date_parts[ :short ] = show_circa + year + show_era
|
133
|
+
@date_parts[ :long ] = @date_parts[ :short ]
|
134
|
+
@date_parts[ :full ] = @date_parts[ :long ]
|
135
|
+
end
|
136
|
+
|
137
|
+
@date_parts
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
def clean_parameter( date )
|
142
|
+
date.to_s.strip if date.respond_to? :to_s
|
143
|
+
end
|
144
|
+
|
145
|
+
def massage( date )
|
146
|
+
|
147
|
+
date_in_parts = []
|
148
|
+
|
149
|
+
date_separator = Regexp.new DATE_SEPARATOR, true
|
150
|
+
|
151
|
+
#- Split the string
|
152
|
+
|
153
|
+
date_in_parts = date.split date_separator
|
154
|
+
date_in_parts.delete_if { |d| d.to_s.empty? }
|
155
|
+
if date_in_parts.first.match Regexp.new( @circa_words.join( '|' ), true )
|
156
|
+
@date_parts[ :circa ] = true
|
157
|
+
date_in_parts.shift
|
158
|
+
end
|
159
|
+
if date_in_parts.last.match Regexp.new( @era_words.join( '|' ), true )
|
160
|
+
@date_parts[ :era ] = date_in_parts.pop.upcase.strip
|
161
|
+
end
|
162
|
+
|
163
|
+
date_in_parts.join '-'
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -1,153 +1,12 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
1
|
class FuzzyDate
|
2
|
+
|
4
3
|
def initialize( date, euro = false )
|
5
4
|
setup
|
6
5
|
analyze date, euro
|
7
6
|
end
|
8
7
|
|
9
|
-
def analyze( date, euro )
|
10
|
-
|
11
|
-
date = clean_parameter date
|
12
|
-
|
13
|
-
@date_parts[ :original ] = date
|
14
|
-
|
15
|
-
date = massage date
|
16
|
-
@date_parts[ :fixed ] = date
|
17
|
-
|
18
|
-
#- Takes care of YYYY
|
19
|
-
if date =~ /^(\d{1,4})$/
|
20
|
-
year = $1.to_i.to_s
|
21
|
-
month = nil
|
22
|
-
day = nil
|
23
|
-
|
24
|
-
#- Takes care of YYYY-MM-DD and YYYY-MM
|
25
|
-
elsif date =~ /^(\d{3,4})(?:-(\d{1,2})(?:-(\d{1,2}))?)?$/
|
26
|
-
year = $1.to_i.to_s
|
27
|
-
month = $2 ? $2.to_i.to_s : nil
|
28
|
-
day = $3 ? $3.to_i.to_s : nil
|
29
|
-
|
30
|
-
#- Takes care of DD-MM-YYYY
|
31
|
-
elsif date =~ /^(\d{1,2})-(\d{1,2})-(\d{1,4})$/ and euro
|
32
|
-
day = $1.to_i.to_s
|
33
|
-
month = $2.to_i.to_s
|
34
|
-
year = $3.to_i.to_s
|
35
|
-
|
36
|
-
#- Takes care of MM-DD-YYYY
|
37
|
-
elsif date =~ /^(\d{1,2})-(\d{1,2})-(\d{1,4})$/
|
38
|
-
month = $1.to_i.to_s
|
39
|
-
day = $2.to_i.to_s
|
40
|
-
year = $3.to_i.to_s
|
41
|
-
|
42
|
-
#- Takes care of MM-YYYY
|
43
|
-
elsif date =~ /^(\d{1,2})-(\d{1,4})?$/
|
44
|
-
month = $1.to_i.to_s
|
45
|
-
day = nil
|
46
|
-
year = $2.to_i.to_s
|
47
|
-
|
48
|
-
#- Takes care of DD-MMM-YYYY and DD-MMM
|
49
|
-
elsif date =~ /^(\d{1,2})(?:-(#{ @month_abbreviations.keys.join( '|' ) }).*?(?:-(\d{1,4}))?)?$/i
|
50
|
-
month_text = $2.to_s.capitalize
|
51
|
-
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
52
|
-
day = $1.to_i.to_s
|
53
|
-
year = $3 ? $3.to_i.to_s : nil
|
54
|
-
|
55
|
-
#- Takes care of MMM-DD-YYYY
|
56
|
-
elsif date =~ /^(#{ @month_abbreviations.keys.join( '|' ) }).*?-(\d{1,2})-(\d{1,4})$/i
|
57
|
-
month_text = $1.to_s.capitalize
|
58
|
-
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
59
|
-
day = $2.to_i.to_s
|
60
|
-
year = $3 ? $3.to_i.to_s : nil
|
61
|
-
|
62
|
-
#- Takes care of MMM-YYYY and MMM
|
63
|
-
elsif date =~ /^(#{ @month_abbreviations.keys.join( '|' ) }).*?(?:-(\d{1,4}))?$/i
|
64
|
-
month_text = $1.to_s.capitalize
|
65
|
-
month = @month_names.key( @month_abbreviations[ month_text ] ).to_i.to_s
|
66
|
-
day = nil
|
67
|
-
year = $2 ? $2.to_i.to_s : nil
|
68
|
-
|
69
|
-
else
|
70
|
-
raise ArgumentError.new( 'Cannot parse date.' )
|
71
|
-
end
|
72
|
-
|
73
|
-
@date_parts[ :year ] = year ? year.to_i : nil
|
74
|
-
@date_parts[ :month ] = month ? month.to_i : nil
|
75
|
-
@date_parts[ :day ] = day ? day.to_i : nil
|
76
|
-
#return { :circa => "day: #{ day }, month: #{ month }, year: #{ year }" }
|
77
|
-
|
78
|
-
#- Some error checking at this point
|
79
|
-
if month.to_i > 13
|
80
|
-
raise ArgumentError.new( 'Month cannot be greater than 12.' )
|
81
|
-
elsif month and day and day.to_i > @days_in_month[ month.to_i ]
|
82
|
-
unless month.to_i == 2 and year and Date.parse( '1/1/' + year ).leap? and day.to_i == 29
|
83
|
-
raise ArgumentError.new( 'Too many days in this month.' )
|
84
|
-
end
|
85
|
-
elsif month and month.to_i < 1
|
86
|
-
raise ArgumentError.new( 'Month cannot be less than 1.' )
|
87
|
-
elsif day and day.to_i < 1
|
88
|
-
raise ArgumentError.new( 'Day cannot be less than 1.' )
|
89
|
-
end
|
90
|
-
|
91
|
-
month_name = @month_names[ month.to_i ]
|
92
|
-
@date_parts[ :month_name ] = month_name
|
93
|
-
|
94
|
-
# ----------------------------------------------------------------------
|
95
|
-
|
96
|
-
show_era = ' ' + @date_parts[ :era ]
|
97
|
-
show_circa = @date_parts[ :circa ] == true ? 'About ' : ''
|
98
|
-
|
99
|
-
if year and month and day
|
100
|
-
@date_parts[ :short ] = show_circa + month + '/' + day + '/' + year + show_era
|
101
|
-
@date_parts[ :long ] = show_circa + month_name + ' ' + day + ', ' + year + show_era
|
102
|
-
modified_long = show_circa + month_name + ' ' + day + ', ' + year.rjust( 4, "0" ) + show_era
|
103
|
-
@date_parts[ :full ] = show_circa + Date.parse( modified_long ).strftime( '%A,' ) + Date.parse( day + ' ' + month_name + ' ' + year.rjust( 4, "0" ) ).strftime( ' %B %-1d, %Y' ) + show_era
|
104
|
-
elsif year and month
|
105
|
-
@date_parts[ :short ] = show_circa + month + '/' + year + show_era
|
106
|
-
@date_parts[ :long ] = show_circa + month_name + ', ' + year + show_era
|
107
|
-
@date_parts[ :full ] = @date_parts[ :long ]
|
108
|
-
elsif month and day
|
109
|
-
month_text = @month_abbreviations.key(month_text) || month_text
|
110
|
-
@date_parts[ :short ] = show_circa + day + '-' + month_text
|
111
|
-
@date_parts[ :long ] = show_circa + day + ' ' + month_name
|
112
|
-
@date_parts[ :full ] = @date_parts[ :long ]
|
113
|
-
elsif year
|
114
|
-
@date_parts[ :short ] = show_circa + year + show_era
|
115
|
-
@date_parts[ :long ] = @date_parts[ :short ]
|
116
|
-
@date_parts[ :full ] = @date_parts[ :long ]
|
117
|
-
end
|
118
|
-
|
119
|
-
@date_parts
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
8
|
def to_hash
|
124
9
|
@date_parts
|
125
10
|
end
|
126
11
|
|
127
|
-
private
|
128
|
-
|
129
|
-
def clean_parameter( date )
|
130
|
-
date.to_s.strip if date.respond_to? :to_s
|
131
|
-
end
|
132
|
-
|
133
|
-
def massage( date )
|
134
|
-
|
135
|
-
date_in_parts = []
|
136
|
-
|
137
|
-
date_separator = Regexp.new DATE_SEPARATOR, true
|
138
|
-
|
139
|
-
#- Split the string
|
140
|
-
|
141
|
-
date_in_parts = date.split date_separator
|
142
|
-
date_in_parts.delete_if { |d| d.to_s.empty? }
|
143
|
-
if date_in_parts.first.match Regexp.new( @circa_words.join( '|' ), true )
|
144
|
-
@date_parts[ :circa ] = true
|
145
|
-
date_in_parts.shift
|
146
|
-
end
|
147
|
-
if date_in_parts.last.match Regexp.new( @era_words.join( '|' ), true )
|
148
|
-
@date_parts[ :era ] = date_in_parts.pop.upcase.strip
|
149
|
-
end
|
150
|
-
|
151
|
-
date_in_parts.join '-'
|
152
|
-
end
|
153
12
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fuzzy-date
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cole
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The fuzzy-date gem provides a way to parse and use incomplete dates,
|
14
14
|
like those found in history or genealogy.
|
@@ -24,6 +24,7 @@ files:
|
|
24
24
|
- lib/fuzzy-date.rb
|
25
25
|
- lib/fuzzy-date/fuzzy-date.rb
|
26
26
|
- lib/fuzzy-date/variables.rb
|
27
|
+
- lib/fuzzy-date/analyze.rb
|
27
28
|
homepage: https://github.com/davidcole/fuzzy-date
|
28
29
|
licenses:
|
29
30
|
- MIT
|