Class: FuzzyDate
Overview
A fuzzy date is a representation of a date which may well be incomplete or imprecise. You can enter the exact date or for example just the day of the week or the year or a combination thereof. One can also add the Circa prefix to any date. The FuzzyDate object is immutable so if you wish to change a FuzzyDate value it is neccessary to create a new FuzzyDate.
Defined Under Namespace
Classes: FDate
Class Method Summary collapse
-
.new_from_date(date) ⇒ Object
create a FuzzyDate object from a Date object.
-
.new_from_db(i) ⇒ Object
create a new FuzzyDate object from the database formatted integer.
-
.parse(str) ⇒ Object
create a new date object by parsing a string.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
-
#bce? ⇒ Boolean
is the date before the year zero.
-
#birthday ⇒ Object
return an integer representing only the month and day.
-
#circa? ⇒ Boolean
is the date approximate ?.
-
#complete? ⇒ Boolean
is the date complete.
-
#day ⇒ Object
returns the day of the month ( 1..n ).
-
#initialize(year = nil, month = nil, day = nil, wday = nil, circa = nil) ⇒ FuzzyDate
constructor
create a new FuzzyDate object.
-
#month ⇒ Object
returns the month number (1..12).
-
#to_date ⇒ Object
if the date is complete then return a regular Date object.
-
#to_db ⇒ Object
convert the fuzzy date into a format which can be stored in a database.
-
#to_i ⇒ Object
convert to integer format.
-
#to_s ⇒ Object
convert to a human readable string.
-
#unknown? ⇒ Boolean
is the date completely unknown.
-
#wday ⇒ Object
returns an integer representing the day of the week, 0..6 with Sunday=0.
-
#year ⇒ Object
returns the year number (including century).
Constructor Details
#initialize(year = nil, month = nil, day = nil, wday = nil, circa = nil) ⇒ FuzzyDate
create a new FuzzyDate object. There are no checks here to validate if the date is valid or not.. eg there is no check that the day of the week actually corresponds to the actual date if completely specified.
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/fuzzy_date.rb', line 60 def initialize(year=nil,month=nil,day=nil,wday=nil,circa=nil) raise "FuzzyDate: invalid month" if month && ((month>12) || (month<1)) raise "FuzzyDate: invalid day" if day && ((day>31) || (day<1)) raise "FuzzyDate: invalid weekday" if wday && ((wday>6) || (wday<0)) raise "FuzzyDate: year too big !" if year && (year.abs > 99999999999 ) @year = year && year.abs @month = month @day = day @wday = wday @circa = circa @bce = year && (year.to_i < 0) end |
Class Method Details
.new_from_date(date) ⇒ Object
create a FuzzyDate object from a Date object
209 210 211 |
# File 'lib/fuzzy_date.rb', line 209 def self.new_from_date( date) new(date.year,date.month,date.day) end |
.new_from_db(i) ⇒ Object
create a new FuzzyDate object from the database formatted integer.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/fuzzy_date.rb', line 164 def self.new_from_db(i) return nil unless i str = i.to_s return nil if str == '0' bce = false raise "Invalid Fuzzy Time String - #{str}" unless str =~/^[+-]?\d{6,}$/ str.sub!(/^-/){|m| bce= true;""} str = ("000000" + str)[-7,7] if str.length < 7 circa = (str[-1,1] == '1') year = (str[-2,1] == '1' ? nil : 0) wday = str[-3,1].to_i - 1 day = str[-5,2].to_i month = str[-7,2].to_i wday = nil if ((wday<0) || (wday>6)) day = nil if ((day==0) || (day>31)) month = nil if ((month==0) || (month > 12)) year = (str[0..-8].to_i > 0 ? str[0..-8].to_i : year ) year = -year if year && bce new(year,month,day,wday,circa) end |
.parse(str) ⇒ Object
create a new date object by parsing a string
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/fuzzy_date.rb', line 214 def self.parse( str ) return unless str && str.length > 0 continue = true circa = false bce = false unknown = false #filter out 'c' or 'circa' str.sub!(/CIRCA/i){|m| circa=true;continue=nil} if continue str.sub!(/^CA /i){|m| circa=true;continue=nil} if continue str.sub!(/^C /i){|m| circa=true;continue=nil} if continue str.sub!(/ABOUT/i){|m| circa=true;continue=nil} if continue str.sub!(/AROUND/i){|m| circa=true;continue=nil} if continue str.sub!(/ROUND/i){|m| circa=true;continue=nil} if continue str.sub!(/APPROX/i){|m| circa=true;continue=nil} if continue str.sub!(/APPROXIMATELY/i){|m| circa=true;continue=nil} if continue #filter out 'bc' 'bce' continue = true str.sub!(/BCE/i){|m| bce=true;continue=nil} str.sub!(/BC/i){|m| bce=true;continue=nil} if continue #filter out 'unknown' continue = true str.sub!(/UNKNOWN/i){|m| unknown=true;continue=nil} # if date is unknown then return an empty FuzzyDate return self.new if unknown # now try to parse the remaining string with the Date parse # method. components= FDate._parse(str,false) year = components[:year] month = components[:mon] day = components[:mday] wday = components[:wday] # fudge the results a bit year,day = day,nil if (day && !month && !year) || (!year && (day.to_i > 31)) if year && year < 0 year = year.abs bce = true end year = -year if bce self.new(year,month,day,wday,circa) end |
Instance Method Details
#<=>(other) ⇒ Object
265 |
# File 'lib/fuzzy_date.rb', line 265 def <=>(other) self.to_db <=> other.to_db end |
#bce? ⇒ Boolean
is the date before the year zero.
104 105 106 |
# File 'lib/fuzzy_date.rb', line 104 def bce? @bce end |
#birthday ⇒ Object
return an integer representing only the month and day
109 110 111 |
# File 'lib/fuzzy_date.rb', line 109 def birthday month * 100 + day if month && day end |
#circa? ⇒ Boolean
is the date approximate ?
99 100 101 |
# File 'lib/fuzzy_date.rb', line 99 def circa? @circa end |
#complete? ⇒ Boolean
is the date complete
114 115 116 |
# File 'lib/fuzzy_date.rb', line 114 def complete? year && (month && month < 13) && (day && day < 32) end |
#day ⇒ Object
returns the day of the month ( 1..n ). returns nil if not known.
84 85 86 |
# File 'lib/fuzzy_date.rb', line 84 def day @day end |
#month ⇒ Object
returns the month number (1..12). returns nil if not known.
89 90 91 |
# File 'lib/fuzzy_date.rb', line 89 def month @month end |
#to_date ⇒ Object
if the date is complete then return a regular Date object
203 204 205 206 |
# File 'lib/fuzzy_date.rb', line 203 def to_date return nil unless complete? Date.new(@year,@month,@day) end |
#to_db ⇒ Object
convert the fuzzy date into a format which can be stored in a database. The storage format is integer format (BIGINT) with digits having the following positional significance:
(-/+) (YYYYYYYYYYY.....Y)MMDDd[01][01]
where + is AD or CE
- is BC or BCE
1 at end = circa or C otherwise 0
1 at 2nd from end = year unknown - otherwise missing year = year 0
YYYYY is the year number 0 or missing = year absent OR value is unknown
MM is the month number or 13 for unknown
DD is the day of the month or 32 for unknown
d is the day of the week where 8 = unknown, 1=Sunday .. 7=Saturday
this wierd format has been chosen to allow sorting within the database and to
avoid leading zeros containing information from being stripped from the representation.
save in a mysql database in format BIGINT
149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/fuzzy_date.rb', line 149 def to_db str = '' str= str + (@year > 0 ? @year.to_s : '') if @year str= str + (@month ? "%02d" % @month.to_s : '13') str= str + (@day ? "%02d" % @day.to_s : '32') str= str + (@wday ? (@wday+1).to_s : '8') str= str + (@year ? '0' : '1') str= str + (@circa ? '1' : '0') i = str.to_i i = -i if @bce i end |
#to_i ⇒ Object
convert to integer format
124 125 126 |
# File 'lib/fuzzy_date.rb', line 124 def to_i to_db end |
#to_s ⇒ Object
convert to a human readable string
186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/fuzzy_date.rb', line 186 def to_s if unknown? str = "unknown" else str = "" str = "circa " if circa? str+= FDate::DAYNAMES[wday] + " " if wday str+= day.to_s + " " if day str+= FDate::MONTHNAMES[month] + " " if month str+= year.to_s if year str += " bce" if bce? str.strip end end |
#unknown? ⇒ Boolean
is the date completely unknown
119 120 121 |
# File 'lib/fuzzy_date.rb', line 119 def unknown? !@year && !@month && !@day && !@wday end |
#wday ⇒ Object
returns an integer representing the day of the week, 0..6 with Sunday=0. returns nil if not known.
75 76 77 78 79 80 81 |
# File 'lib/fuzzy_date.rb', line 75 def wday if !@wday && complete? && (@year > 0) to_date.wday else @wday end end |
#year ⇒ Object
returns the year number (including century)
94 95 96 |
# File 'lib/fuzzy_date.rb', line 94 def year @year end |