third_base 1.0.0
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.
- data/LICENSE +19 -0
- data/README +261 -0
- data/benchmark/date.rb +18 -0
- data/benchmark/datetime.rb +18 -0
- data/bin/third_base +4 -0
- data/lib/third_base/compat/date/format.rb +3 -0
- data/lib/third_base/compat/date.rb +3 -0
- data/lib/third_base/compat.rb +405 -0
- data/lib/third_base/date.rb +674 -0
- data/lib/third_base/datetime.rb +385 -0
- data/lib/third_base.rb +2 -0
- data/spec/compat/compat_class_methods_spec.rb +208 -0
- data/spec/compat/compat_instance_methods_spec.rb +54 -0
- data/spec/compat/date_spec.rb +56 -0
- data/spec/compat/datetime_spec.rb +77 -0
- data/spec/compat_spec_helper.rb +2 -0
- data/spec/date/accessor_spec.rb +134 -0
- data/spec/date/add_month_spec.rb +28 -0
- data/spec/date/add_spec.rb +24 -0
- data/spec/date/boat_spec.rb +31 -0
- data/spec/date/civil_spec.rb +47 -0
- data/spec/date/commercial_spec.rb +34 -0
- data/spec/date/constants_spec.rb +18 -0
- data/spec/date/downto_spec.rb +17 -0
- data/spec/date/eql_spec.rb +9 -0
- data/spec/date/hash_spec.rb +13 -0
- data/spec/date/julian_spec.rb +13 -0
- data/spec/date/leap_spec.rb +19 -0
- data/spec/date/minus_month_spec.rb +26 -0
- data/spec/date/minus_spec.rb +47 -0
- data/spec/date/ordinal_spec.rb +13 -0
- data/spec/date/parse_spec.rb +227 -0
- data/spec/date/step_spec.rb +55 -0
- data/spec/date/strftime_spec.rb +132 -0
- data/spec/date/strptime_spec.rb +118 -0
- data/spec/date/succ_spec.rb +16 -0
- data/spec/date/today_spec.rb +11 -0
- data/spec/date/upto_spec.rb +17 -0
- data/spec/date_spec_helper.rb +3 -0
- data/spec/datetime/accessor_spec.rb +53 -0
- data/spec/datetime/add_spec.rb +36 -0
- data/spec/datetime/boat_spec.rb +43 -0
- data/spec/datetime/constructor_spec.rb +58 -0
- data/spec/datetime/eql_spec.rb +11 -0
- data/spec/datetime/minus_spec.rb +65 -0
- data/spec/datetime/now_spec.rb +14 -0
- data/spec/datetime/parse_spec.rb +338 -0
- data/spec/datetime/strftime_spec.rb +102 -0
- data/spec/datetime/strptime_spec.rb +84 -0
- data/spec/datetime_spec_helper.rb +3 -0
- data/spec/spec_helper.rb +54 -0
- metadata +107 -0
@@ -0,0 +1,405 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'third_base'
|
3
|
+
|
4
|
+
Object.send(:remove_const, :Date) if Object.const_get(:Date) rescue nil
|
5
|
+
Object.send(:remove_const, :DateTime) if Object.const_get(:DateTime) rescue nil
|
6
|
+
|
7
|
+
module ThirdBase
|
8
|
+
MJD_JD = 2400001
|
9
|
+
LD_JD = 2299160
|
10
|
+
ITALY = 2299161
|
11
|
+
ENGLAND = 2361222
|
12
|
+
JULIAN = -100000000000000000000000000000000000
|
13
|
+
GREGORIAN = 100000000000000000000000000000000000
|
14
|
+
|
15
|
+
# Compatibility class methods for Date and DateTime, necessary because ruby doesn't
|
16
|
+
# support multiple inheritance.
|
17
|
+
module CompatClassMethods
|
18
|
+
[ %w(os? julian?),
|
19
|
+
%w(ns? gregorian?),
|
20
|
+
%w(exist1? valid_jd?),
|
21
|
+
%w(exist2? valid_ordinal?),
|
22
|
+
%w(exist3? valid_date?),
|
23
|
+
%w(exist? valid_date?),
|
24
|
+
%w(existw? valid_commercial?),
|
25
|
+
%w(new0 new!),
|
26
|
+
%w(new1 jd),
|
27
|
+
%w(new2 ordinal),
|
28
|
+
%w(new3 new),
|
29
|
+
%w(neww commercial)
|
30
|
+
].each{|old, new| module_eval("def #{old}(*args, &block); #{new}(*args, &block); end")}
|
31
|
+
|
32
|
+
# Return the parts of the parsed date as a hash witht he following keys:
|
33
|
+
#
|
34
|
+
# * :hour : hour
|
35
|
+
# * :mday : day of month
|
36
|
+
# * :min : minute
|
37
|
+
# * :mon : month
|
38
|
+
# * :offset : time zone offset from UTC in seconds
|
39
|
+
# * :sec : second
|
40
|
+
# * :sec_fraction : fraction of a second
|
41
|
+
# * :year : year
|
42
|
+
# * :zone : time zone offset as string
|
43
|
+
def _parse(str, comp=false)
|
44
|
+
d = DateTime.parse(str)
|
45
|
+
{:mon=>d.mon, :zone=>d.zone, :sec=>d.sec, :year=>d.year, :hour=>d.hour, :offset=>d.offset, :mday=>d.day, :min=>d.min, :sec_fraction=>d.usec/1000000.0}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Converts an Astronomical Julian Date to an Astronomical Modified Julian Date (substracts an integer from ajd)
|
49
|
+
def ajd_to_amjd(ajd)
|
50
|
+
ajd - MJD_JD
|
51
|
+
end
|
52
|
+
|
53
|
+
# Converts an Astronomical Julian Date to a Julian Date (returns ajd, ignores of)
|
54
|
+
def ajd_to_jd(ajd, of=0)
|
55
|
+
ajd
|
56
|
+
end
|
57
|
+
|
58
|
+
# Converts an Astronomical Modified Julian Date to an Astronomical Julian Date (adds an integer to amjd)
|
59
|
+
def amjd_to_ajd(amjd)
|
60
|
+
amjd + MJD_JD
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the julian date for the given civil date arguments, ignores sg.
|
64
|
+
def civil_to_jd(year, mon, day, sg=nil)
|
65
|
+
civil(year, mon, day).jd
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the julian date for the given commercial date arguments, ignores sg.
|
69
|
+
def commercial_to_jd(cwyear, cweek, cwday, sg=nil)
|
70
|
+
commercial(cwyear, cweek, cwday).jd
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the fraction of the date as an array of hours, minutes, seconds, and fraction on a second.
|
74
|
+
def day_fraction_to_time(fr)
|
75
|
+
hours, fr = (fr * 24).divmod(1)
|
76
|
+
minutes, fr = (fr * 60).divmod(1)
|
77
|
+
seconds, sec_fract = (fr * 60).divmod(1)
|
78
|
+
[hours, minutes, seconds, sec_fract]
|
79
|
+
end
|
80
|
+
|
81
|
+
# True if jd is greater than sg, false otherwise.
|
82
|
+
def gregorian?(jd, sg)
|
83
|
+
jd > sg
|
84
|
+
end
|
85
|
+
|
86
|
+
# All years divisible by 4 are leap years in the Gregorian calendar,
|
87
|
+
# except for years divisible by 100 and not by 400.
|
88
|
+
def leap?(y)
|
89
|
+
y % 4 == 0 && y % 100 != 0 || y % 400 == 0
|
90
|
+
end
|
91
|
+
alias gregorian_leap? leap?
|
92
|
+
|
93
|
+
# Converts a Julian Date to an Astronomical Julian Date (returns j, ignores fr and of)
|
94
|
+
def jd_to_ajd(j, fr, of=0)
|
95
|
+
j
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns [year, month, day] for the given julian date, ignores sg.
|
99
|
+
def jd_to_civil(j, sg=nil)
|
100
|
+
jd(j).send(:civil)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns [cwyear, cweek, cwday] for the given julian date, ignores sg.
|
104
|
+
def jd_to_commercial(j, sg=nil)
|
105
|
+
jd(j).send(:commercial)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Converts a julian date to the number of days since the adoption of
|
109
|
+
# the gregorian calendar in Italy (subtracts an integer from j).
|
110
|
+
def jd_to_ld(j)
|
111
|
+
j - LD_JD
|
112
|
+
end
|
113
|
+
|
114
|
+
# Convert a Julian Date to a Modified Julian Date (subtracts an integer from j).
|
115
|
+
def jd_to_mjd(j)
|
116
|
+
j - MJD_JD
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns [year, yday] for the given julian date, ignores sg.
|
120
|
+
def jd_to_ordinal(j, sg=nil)
|
121
|
+
jd(j).send(:ordinal)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns the day of week for the given julian date.
|
125
|
+
def jd_to_wday(j)
|
126
|
+
jd(j).wday
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns true if jd is less than sg, false otherwise.
|
130
|
+
def julian?(jd, sg)
|
131
|
+
jd < sg
|
132
|
+
end
|
133
|
+
|
134
|
+
# All years divisible by 4 are leap years in the Julian calendar.
|
135
|
+
def julian_leap?(y)
|
136
|
+
y % 4 == 0
|
137
|
+
end
|
138
|
+
|
139
|
+
# Converts a number of days since the adoption of the gregorian calendar in Italy
|
140
|
+
# to a julian date (adds an integer to ld).
|
141
|
+
def ld_to_jd(ld)
|
142
|
+
ld + LD_JD
|
143
|
+
end
|
144
|
+
|
145
|
+
# Converts a Modified Julian Date to a Julian Date (adds an integer to mjd).
|
146
|
+
def mjd_to_jd(mjd)
|
147
|
+
mjd + MJD_JD
|
148
|
+
end
|
149
|
+
|
150
|
+
# Converts the given year and day of year to a julian date, ignores sg.
|
151
|
+
def ordinal_to_jd(year, yday, sg=nil)
|
152
|
+
ordinal(year, yday).jd
|
153
|
+
end
|
154
|
+
|
155
|
+
# Converts the given hour, minute, and second to a fraction of a day as a Float.
|
156
|
+
def time_to_day_fraction(h, min, s)
|
157
|
+
(h*3600 + min*60 + s)/86400.0
|
158
|
+
end
|
159
|
+
|
160
|
+
# Return the julian date of the given year, month, and day if valid, or nil if not, ignores sg.
|
161
|
+
def valid_civil?(year, mon, day, sg=nil)
|
162
|
+
civil(year, mon, day).jd rescue nil
|
163
|
+
end
|
164
|
+
alias valid_date? valid_civil?
|
165
|
+
|
166
|
+
# Return the julian date of the given commercial week year, commercial week, and commercial
|
167
|
+
# week day if valid, or nil if not, ignores sg.
|
168
|
+
def valid_commercial?(cwyear, cweek, cwday, sg=nil)
|
169
|
+
commercial(cwyear, cweek, cwday).jd rescue nil
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns the julian date if valid (always returns jd, ignores sg).
|
173
|
+
def valid_jd?(jd, sg=nil)
|
174
|
+
jd
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return the julian date of the given year and day of year if valid, or nil if not, ignores sg.
|
178
|
+
def valid_ordinal?(year, yday, sg=nil)
|
179
|
+
ordinal(year, yday).jd rescue nil
|
180
|
+
end
|
181
|
+
|
182
|
+
# Returns the fraction of the day if the time is valid, or nil if the time is not valid.
|
183
|
+
def valid_time?(h, min, s)
|
184
|
+
h += 24 if h < 0
|
185
|
+
min += 60 if min < 0
|
186
|
+
s += 60 if s < 0
|
187
|
+
return unless ((0..23) === h &&
|
188
|
+
(0..59) === min &&
|
189
|
+
(0..59) === s) ||
|
190
|
+
(24 == h &&
|
191
|
+
0 == min &&
|
192
|
+
0 == s)
|
193
|
+
time_to_day_fraction(h, min, s)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Converts a time zone string to a offset from UTC in seconds.
|
197
|
+
def zone_to_diff(zone)
|
198
|
+
if m = /\A([+-](?:\d{4}|\d\d:\d\d))\z/.match(zone)
|
199
|
+
x = m[1].gsub(':','')
|
200
|
+
x[0..2].to_i*3600 + x[3..4].to_i*60
|
201
|
+
else
|
202
|
+
0
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Compatibility instance methods for Date and DateTime, necessary because ruby doesn't
|
208
|
+
# support multiple inheritance.
|
209
|
+
module CompatInstanceMethods
|
210
|
+
# Returns the Astronomical Julian Date for this date (alias for jd)
|
211
|
+
def ajd
|
212
|
+
jd
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns the Astronomical Modified Julian Date for this date (jd plus an integer)
|
216
|
+
def amjd
|
217
|
+
jd - MJD_JD
|
218
|
+
end
|
219
|
+
alias mjd amjd
|
220
|
+
|
221
|
+
# Returns self.
|
222
|
+
def gregorian
|
223
|
+
self
|
224
|
+
end
|
225
|
+
alias england gregorian
|
226
|
+
alias julian gregorian
|
227
|
+
alias italy gregorian
|
228
|
+
|
229
|
+
# True, since the gregorian calendar is always used.
|
230
|
+
def gregorian?
|
231
|
+
true
|
232
|
+
end
|
233
|
+
alias ns? gregorian?
|
234
|
+
|
235
|
+
# False, since the gregorian calendar is never used.
|
236
|
+
def julian?
|
237
|
+
false
|
238
|
+
end
|
239
|
+
alias os? julian?
|
240
|
+
|
241
|
+
# Returns the days since the date of the adoption of the gregorian calendar in Italy
|
242
|
+
# (substracts an integer from jd).
|
243
|
+
def ld
|
244
|
+
jd - LD_JD
|
245
|
+
end
|
246
|
+
|
247
|
+
# Alias for day.
|
248
|
+
def mday
|
249
|
+
day
|
250
|
+
end
|
251
|
+
|
252
|
+
# Returns self, ignores sg.
|
253
|
+
def new_start(sg=nil)
|
254
|
+
self
|
255
|
+
end
|
256
|
+
alias newsg new_start
|
257
|
+
|
258
|
+
# Returns 0, since the gregorian calendar is always used.
|
259
|
+
def start
|
260
|
+
0
|
261
|
+
end
|
262
|
+
alias sg start
|
263
|
+
end
|
264
|
+
|
265
|
+
# ThirdBase's top level Date compatibility class, striving to be as close as possible
|
266
|
+
# to the standard Date class's API.
|
267
|
+
class ::Date < Date
|
268
|
+
extend CompatClassMethods
|
269
|
+
include CompatInstanceMethods
|
270
|
+
|
271
|
+
# Parse the date using strptime with the given format.
|
272
|
+
def self._strptime(str, fmt='%F')
|
273
|
+
strptime(str, fmt)
|
274
|
+
end
|
275
|
+
|
276
|
+
# Creates a new Date with the given year, month, and day of month, ignores sg.
|
277
|
+
def self.civil(year=-4712, mon=1, day=1, sg=nil)
|
278
|
+
super(year, mon, day)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Creates a new Date with the given commercial week year, commercial week, and commercial week day, ignores sg.
|
282
|
+
def self.commercial(cwyear=1582, cweek=41, cwday=5, sg=nil)
|
283
|
+
super(cwyear, cweek, cwday)
|
284
|
+
end
|
285
|
+
|
286
|
+
# Creates a new Date with the given julian date, ignores sg.
|
287
|
+
def self.jd(j=0, sg=nil)
|
288
|
+
super(j)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Creates a new Date with the given year and day of year, ignores sg.
|
292
|
+
def self.ordinal(year=-4712, yday=1, sg=nil)
|
293
|
+
super(year, yday)
|
294
|
+
end
|
295
|
+
|
296
|
+
# Parse given string using ThirdBase::Date's date parser, ignores comp and sg.
|
297
|
+
def self.parse(str="-4712-01-01", comp=false, sg=nil)
|
298
|
+
super(str)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Parse given string using given format, ignores sg.
|
302
|
+
def self.strptime(str="-4712-01-01", fmt='%F', sg=nil)
|
303
|
+
super(str, fmt)
|
304
|
+
end
|
305
|
+
|
306
|
+
# Creates a new Date with today's date, ignores sg.
|
307
|
+
def self.today(sg=nil)
|
308
|
+
super()
|
309
|
+
end
|
310
|
+
|
311
|
+
# Returns a formatted string representing the date.
|
312
|
+
def asctime
|
313
|
+
strftime('%a %b %e 00:00:00 %Y')
|
314
|
+
end
|
315
|
+
alias ctime asctime
|
316
|
+
|
317
|
+
# Returns 0.0, since Date don't have fractional days.
|
318
|
+
def day_fraction
|
319
|
+
0.0
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# ThirdBase's top level DateTime compatibility class, striving to be as close as possible
|
324
|
+
# to the standard DateTime class's API.
|
325
|
+
class ::DateTime < DateTime
|
326
|
+
extend CompatClassMethods
|
327
|
+
include CompatInstanceMethods
|
328
|
+
|
329
|
+
# Parse the datetime using strptime with the given format.
|
330
|
+
def self._strptime(str, fmt='%FT%T%z')
|
331
|
+
strptime(str, fmt)
|
332
|
+
end
|
333
|
+
|
334
|
+
# Creates a new DateTime with the given year, month, day of month, hour, minute, second, and offset, ignores sg.
|
335
|
+
def self.civil(year=-4712, mon=1, day=1, hour=0, min=0, sec=0, offset=0, sg=nil)
|
336
|
+
super(year, mon, day, hour, min, sec, 0, (offset*86400).to_i)
|
337
|
+
end
|
338
|
+
|
339
|
+
# Creates a new DateTime with the given commercial week year, commercial week, commercial week day,
|
340
|
+
# hour, minute, second, and offset, ignores sg.
|
341
|
+
def self.commercial(cwyear=1582, cweek=41, cwday=5, hour=0, min=0, sec=0, offset=0, sg=nil)
|
342
|
+
super(cwyear, cweek, cwday, hour, min, sec, 0, (offset*86400).to_i)
|
343
|
+
end
|
344
|
+
|
345
|
+
# Creates a new DateTime with the given julian date, hour, minute, second, and offset, ignores sg.
|
346
|
+
def self.jd(j=0, hour=0, min=0, sec=0, offset=0, sg=nil)
|
347
|
+
super(j, hour, min, sec, 0, (offset*86400).to_i)
|
348
|
+
end
|
349
|
+
|
350
|
+
# Creates a new DateTime with the given year, day of year, hour, minute, second, and offset, ignores sg.
|
351
|
+
def self.ordinal(year=-4712, yday=1, hour=0, min=0, sec=0, offset=0, sg=nil)
|
352
|
+
super(year, yday, hour, min, sec, 0, (offset*86400).to_i)
|
353
|
+
end
|
354
|
+
|
355
|
+
# Parse given string using ThirdBase::DateTime's date parser, ignores comp and sg.
|
356
|
+
def self.parse(str="-4712-01-01T00:00:00+00:00", comp=false, sg=nil)
|
357
|
+
super(str)
|
358
|
+
end
|
359
|
+
|
360
|
+
# Parse given string using given format, ignores sg.
|
361
|
+
def self.strptime(str="-4712-01-01T00:00:00+00:00", fmt='%FT%T%z', sg=nil)
|
362
|
+
super(str, fmt)
|
363
|
+
end
|
364
|
+
|
365
|
+
# Creates a new DateTime with the current date and time, ignores sg.
|
366
|
+
def self.now(sg=nil)
|
367
|
+
super()
|
368
|
+
end
|
369
|
+
|
370
|
+
# Returns a formatted string representing the date.
|
371
|
+
def asctime
|
372
|
+
strftime('%c')
|
373
|
+
end
|
374
|
+
alias ctime asctime
|
375
|
+
|
376
|
+
alias day_fraction fract
|
377
|
+
|
378
|
+
# Returns a new DateTime with the same date and time as this datetime, but with a new offset.
|
379
|
+
def new_offset(offset=0)
|
380
|
+
self.class.new!(:civil=>civil, :parts=>time_parts, :offset=>(offset*86400).to_i)
|
381
|
+
end
|
382
|
+
alias newof new_offset
|
383
|
+
|
384
|
+
# Return the offset as a Float representing the fraction of the day different from UTC.
|
385
|
+
def offset
|
386
|
+
@offset/86400.0
|
387
|
+
end
|
388
|
+
alias of offset
|
389
|
+
|
390
|
+
# Return the offset as a number of seconds from UTC.
|
391
|
+
def offset_sec
|
392
|
+
@offset
|
393
|
+
end
|
394
|
+
|
395
|
+
# The fraction of a second represented as a fraction of the entire day.
|
396
|
+
def sec_fraction
|
397
|
+
usec/86400000000.0
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'compat'))
|
403
|
+
require 'date'
|
404
|
+
require 'date/format'
|
405
|
+
$:.shift
|