-
Notifications
You must be signed in to change notification settings - Fork 26
/
dprecision.rb
150 lines (122 loc) · 3.24 KB
/
dprecision.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env ruby
require 'runt'
require 'date'
module Runt
# :title:DPrecision
# == DPrecision
# Module providing automatic precisioning of Date, DateTime, and PDate classes.
#
# Inspired by a <tt>pattern</tt>[http://martinfowler.com/ap2/timePoint.html] by Martin Fowler.
#
#
# Author:: Matthew Lipper
module DPrecision
def DPrecision.to_p(date,prec=DEFAULT)
case prec
when MIN then PDate.min(*DPrecision.explode(date,prec))
when DAY then PDate.day(*DPrecision.explode(date,prec))
when HOUR then PDate.hour(*DPrecision.explode(date,prec))
when WEEK then PDate.week(*DPrecision.explode(date,prec))
when MONTH then PDate.month(*DPrecision.explode(date,prec))
when YEAR then PDate.year(*DPrecision.explode(date,prec))
when SEC then PDate.sec(*DPrecision.explode(date,prec))
when MILLI then date #raise "Not implemented."
else PDate.default(*DPrecision.explode(date,prec))
end
end
def DPrecision.explode(date,prec)
result = [date.year,date.month,date.day]
if(date.respond_to?("hour"))
result << date.hour << date.min << date.sec
else
result << 0 << 0 << 0
end
result
end
#Simple value class for keeping track of precisioned dates
class Precision
include Comparable
attr_reader :precision
private_class_method :new
#Some constants w/arbitrary integer values used internally for comparisions
YEAR_PREC = 0
MONTH_PREC = 1
WEEK_PREC = 2
DAY_PREC = 3
HOUR_PREC = 4
MIN_PREC = 5
SEC_PREC = 6
MILLI_PREC = 7
#String values for display
LABEL = { YEAR_PREC => "YEAR",
MONTH_PREC => "MONTH",
WEEK_PREC => "WEEK",
DAY_PREC => "DAY",
HOUR_PREC => "HOUR",
MIN_PREC => "MINUTE",
SEC_PREC => "SECOND",
MILLI_PREC => "MILLISECOND"}
#Minimun values that precisioned fields get set to
FIELD_MIN = { YEAR_PREC => 1,
MONTH_PREC => 1,
WEEK_PREC => 1,
DAY_PREC => 1,
HOUR_PREC => 0,
MIN_PREC => 0,
SEC_PREC => 0,
MILLI_PREC => 0}
def Precision.year
new(YEAR_PREC)
end
def Precision.month
new(MONTH_PREC)
end
def Precision.week
new(WEEK_PREC)
end
def Precision.day
new(DAY_PREC)
end
def Precision.hour
new(HOUR_PREC)
end
def Precision.min
new(MIN_PREC)
end
def Precision.sec
new(SEC_PREC)
end
def Precision.millisec
new(MILLI_PREC)
end
def min_value()
FIELD_MIN[@precision]
end
def initialize(prec)
@precision = prec
end
def <=>(other)
self.precision <=> other.precision
end
def ===(other)
self.precision == other.precision
end
def to_s
"DPrecision::#{self.label}"
end
def label
LABEL[@precision]
end
end
#Pseudo Singletons:
YEAR = Precision.year
MONTH = Precision.month
WEEK = Precision.week
DAY = Precision.day
HOUR = Precision.hour
MIN = Precision.min
SEC = Precision.sec
MILLI = Precision.millisec
DEFAULT=MIN
end
end