Module: Ferret::Utils::DateTools

Defined in:
lib/ferret/utils/date_tools.rb

Overview

Provides support for converting dates to strings and vice-versa. The strings are structured so that lexicographic sorting orders by date, which makes them suitable for use as field values and search terms.

Note

dates before 1970 cannot be used, and therefore cannot be indexed

when using this class.

Defined Under Namespace

Classes: Resolution

Constant Summary collapse

SERIALIZED_DATE_LEN =

make date strings long enough to last a millenium

(1000*365*24*60*60*1000).to_s(36).length
MAX_SERIALIZED_DATE_STRING =

The latest date that can be stored in this format

Array.new(SERIALIZED_DATE_LEN, "z").to_s.to_i(36)
MIN_SERIALIZED_DATE_STRING =

The earliest date that can be stored in this format.

DateTools.serialize_time(0)

Class Method Summary collapse

Class Method Details

.date_to_s(date, resolution = Resolution::MILLISECOND) ⇒ Object



68
69
70
# File 'lib/ferret/utils/date_tools.rb', line 68

def DateTools.date_to_s(date, resolution = Resolution::MILLISECOND)
  return time_to_s(Time.parse(date), resolution)
end

.deserialize_time(s) ⇒ Object

Converts a string-encoded date into a millisecond time.



63
64
65
66
# File 'lib/ferret/utils/date_tools.rb', line 63

def DateTools.deserialize_time(s)
  # remember to convert back to seconds
  return Time.at(s.to_i(36)/1000)
end

.round(time, resolution) ⇒ Object

Limit a date’s resolution. For example, the date _2004-09-21 13:50:11_ will be changed to _2004-09-01 00:00:00_ when using Resolution.MONTH.

resolution

The desired resolution of the date to be returned

return

the date with all values more precise than resolution

set to 0 or 1


114
115
116
# File 'lib/ferret/utils/date_tools.rb', line 114

def DateTools.round(time, resolution)
  return s_to_time(time_to_s(time, resolution))
end

.s_to_time(str) ⇒ Object

Converts a string produced by time_to_s or date_to_s back to a time, represented as the number of milliseconds since January 1, 1970, 00:00:00 GMT.

str

the date string to be converted

return

the number of milliseconds since January 1, 1970, 00:00:00GMT



96
97
98
99
100
101
102
103
104
105
# File 'lib/ferret/utils/date_tools.rb', line 96

def DateTools.s_to_time(str)
  year =        str.size >=  4 ? str[ 0.. 3].to_i : nil
  month =       str.size >=  6 ? str[ 4.. 5].to_i : nil
  day =         str.size >=  8 ? str[ 6.. 7].to_i : nil
  hour =        str.size >= 10 ? str[ 8.. 9].to_i : nil
  minute =      str.size >= 12 ? str[10..11].to_i : nil
  second =      str.size >= 14 ? str[12..13].to_i : nil
  microsecond = str.size >= 17 ? str[14..17].to_i*1000 : nil
  return Time.mktime(year, month, day, hour, minute, second, microsecond)
end

.serialize_date(date) ⇒ Object

Converts a Date to a string suitable for indexing. Throws Exception if the date specified in the method argument is before 1970 This method is unsupported. Please use Time instead of Date



32
33
34
# File 'lib/ferret/utils/date_tools.rb', line 32

def DateTools.serialize_date(date)
  return serialize_time(Time.parse(date))
end

.serialize_time(time) ⇒ Object

Converts a millisecond time to a string suitable for indexing. Accepts a Time object or a time in milliseconds.

Throws Exception if the time specified in the method argument is negative, that is, before 1970 It is recommended that you store the date as a string if you don’t need the time to the nearest millisecond. That makes things a lot easier.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/ferret/utils/date_tools.rb', line 43

def DateTools.serialize_time(time)
  if time.instance_of?(Time) then time = time.to_i end

  if (time < 0) then raise("time too early") end

  # convert to milliseconds before serialization
  s = (time*1000).to_s(36)

  if (s.length() > SERIALIZED_DATE_LEN) then raise("time too late") end

  # pad to 16 charactors
  s = "0" + s while (s.length() < SERIALIZED_DATE_LEN)

  return s
end

.time_to_s(time, resolution = Resolution::MILLISECOND) ⇒ Object

Converts a millisecond time to a string suitable for indexing.

time

the date expressed as milliseconds since January 1, 1970,

00:00:00 GMT resolution

the desired resolution, see

#round(long, DateTools.Resolution)
return

a string in format _%Y%m%d%H%M%SSSS_ or shorter, depending on resolution



80
81
82
83
84
85
86
87
88
# File 'lib/ferret/utils/date_tools.rb', line 80

def DateTools.time_to_s(time, resolution = Resolution::MILLISECOND)
  if time.instance_of?(Date) then time = Time.parse(time) end
  suffix = ""
  if (resolution == Resolution::MILLISECOND)
    # the suffix is the number of milliseconds if needed.
    suffix = ((time.to_f-time.to_f.floor)*1000).round.to_s
  end
  return time.strftime(resolution.format) + suffix
end