chronos 0.1.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/CHANGELOG.rdoc +27 -0
- data/HISTORY.rdoc +4 -0
- data/LICENSE.txt +52 -0
- data/MANIFEST.txt +51 -0
- data/NOTES.rdoc +85 -0
- data/README.rdoc +125 -0
- data/Rakefile +34 -0
- data/TODO.rdoc +63 -0
- data/bench/completebench.rb +24 -0
- data/ext/cchronos/extconf.rb +5 -0
- data/ext/chronos_core/extconf.rb +5 -0
- data/lib/chronos.rb +208 -0
- data/lib/chronos/calendar.rb +16 -0
- data/lib/chronos/calendar/gregorian.rb +94 -0
- data/lib/chronos/data/zones.tab +424 -0
- data/lib/chronos/datetime.rb +299 -0
- data/lib/chronos/datetime/gregorian.rb +698 -0
- data/lib/chronos/duration.rb +141 -0
- data/lib/chronos/duration/gregorian.rb +261 -0
- data/lib/chronos/durationtotext.rb +42 -0
- data/lib/chronos/exceptions.rb +16 -0
- data/lib/chronos/gregorian.rb +27 -0
- data/lib/chronos/interval.rb +132 -0
- data/lib/chronos/interval/gregorian.rb +80 -0
- data/lib/chronos/locale/parsers/de_CH.rb +50 -0
- data/lib/chronos/locale/parsers/en_US.rb +1 -0
- data/lib/chronos/locale/parsers/generic.rb +21 -0
- data/lib/chronos/locale/strings/de_DE.yaml +76 -0
- data/lib/chronos/locale/strings/en_US.yaml +76 -0
- data/lib/chronos/minimalistic.rb +37 -0
- data/lib/chronos/numeric/gregorian.rb +100 -0
- data/lib/chronos/ruby.rb +6 -0
- data/lib/chronos/version.rb +21 -0
- data/lib/chronos/zone.rb +212 -0
- data/rake/initialize.rb +116 -0
- data/rake/lib/assesscode.rb +59 -0
- data/rake/lib/bonesplitter.rb +245 -0
- data/rake/lib/projectclass.rb +69 -0
- data/rake/tasks/copyright.rake +24 -0
- data/rake/tasks/gem.rake +119 -0
- data/rake/tasks/git.rake +40 -0
- data/rake/tasks/loc.rake +33 -0
- data/rake/tasks/manifest.rake +63 -0
- data/rake/tasks/meta.rake +16 -0
- data/rake/tasks/notes.rake +36 -0
- data/rake/tasks/post_load.rake +18 -0
- data/rake/tasks/rdoc.rake +73 -0
- data/rake/tasks/rubyforge.rake +67 -0
- data/rake/tasks/spec.rake +55 -0
- data/spec/bacon_helper.rb +43 -0
- data/spec/lib/chronos/datetime/gregorian_spec.rb +314 -0
- data/spec/lib/chronos/datetime_spec.rb +219 -0
- data/spec/lib/chronos_spec.rb +91 -0
- metadata +111 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007-2008 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
# This file is just a shortcut to require all relevent files
|
10
|
+
# for gregorian and setting Chronos to use the gregorian classes
|
11
|
+
# per default.
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
require 'chronos'
|
16
|
+
require 'chronos/calendar/gregorian'
|
17
|
+
require 'chronos/datetime/gregorian'
|
18
|
+
require 'chronos/duration/gregorian'
|
19
|
+
require 'chronos/interval/gregorian'
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
Chronos.use :Gregorian
|
24
|
+
Datetime = Chronos::Datetime::Gregorian
|
25
|
+
Duration = Chronos::Duration::Gregorian
|
26
|
+
Interval = Chronos::Interval::Gregorian
|
27
|
+
Calendar = Chronos::Calendar::Gregorian
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007-2008 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Chronos
|
10
|
+
|
11
|
+
# An Interval is determinated by a start and an end Datetime.
|
12
|
+
# Unlike in Duration, this allows to determine the months part exactly in
|
13
|
+
# seconds (and therefore minutes, hours, days, weeks).
|
14
|
+
# That opens up the possibility to say how
|
15
|
+
class Interval
|
16
|
+
ValidFixed = [:begin, :end].freeze
|
17
|
+
InspectFixedBegin = "<%p [%p] - %p, %p>".freeze
|
18
|
+
InspectFixedEnd = "<%p %p - [%p], %p>".freeze
|
19
|
+
|
20
|
+
# The smaller of the two datetimes
|
21
|
+
attr_reader :begin
|
22
|
+
|
23
|
+
# The bigger of the two datetimes
|
24
|
+
attr_reader :end
|
25
|
+
|
26
|
+
# Which end is fixed, plays a role when adding, subtracting, multiplying, dividing, ...
|
27
|
+
attr_reader :fixed
|
28
|
+
|
29
|
+
# unlike new, between always creates a positive interval
|
30
|
+
# it will switch limit_a and limit_b if limit_a > limit_b
|
31
|
+
# it always fixates :begin
|
32
|
+
def self.between(limit_a, limit_b)
|
33
|
+
limit_a > limit_b ? new(limit_b, limit_a, false, :begin) : new(limit_a, limit_b, false, :begin)
|
34
|
+
end
|
35
|
+
|
36
|
+
# create a new interval that lasts from start_date until end_date
|
37
|
+
# === Arguments
|
38
|
+
# limit_a:: one of the two limiting datetimes
|
39
|
+
# limit_b:: the other of the two limiting datetimes
|
40
|
+
# fixated:: which end to fixate for operations. Defaults to :begin, valid values are (Symbols):
|
41
|
+
# begin:: The smaller datetime is fixated
|
42
|
+
# end:: The smaller datetime is fixated
|
43
|
+
def initialize(limit_a, limit_b, fixed=nil)
|
44
|
+
@fixed = fixed || :begin
|
45
|
+
raise ArgumentError, "limites don't have the same signature" unless (limit_a.time? == limit_b.time? && limit_a.date? == limit_b.date?)
|
46
|
+
raise ArgumentError, "invalid fixed, must be :begin or :end" unless ValidFixed.include?(@fixed)
|
47
|
+
|
48
|
+
@language = limit_a.language
|
49
|
+
|
50
|
+
if limit_a > limit_b then
|
51
|
+
@begin = limit_b
|
52
|
+
@end = limit_a
|
53
|
+
@negative = false
|
54
|
+
else
|
55
|
+
@begin = limit_a
|
56
|
+
@end = limit_b
|
57
|
+
@negative = true
|
58
|
+
end
|
59
|
+
|
60
|
+
overflow = 0
|
61
|
+
picoseconds = @end.ps_number - @begin.ps_number if @begin.time?
|
62
|
+
days = @end.day_number - @begin.day_number if @begin.date?
|
63
|
+
overflow, picoseconds = *picoseconds.divmod(PS_IN_DAY) if @begin.time?
|
64
|
+
@duration = Duration.new(days+overflow, picoseconds, @language)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the same Interval but with begin as fixpoint for operations
|
68
|
+
def fixed_begin
|
69
|
+
self.class.new(@begin, @end, :begin)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the same interval but with end as fixpoint for operations
|
73
|
+
def fixed_end
|
74
|
+
self.class.new(@begin, @end, :end)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Enlarges the Interval by duration away from the fixed end
|
78
|
+
def +(duration)
|
79
|
+
if @fixed == :begin then
|
80
|
+
self.class.new(@begin, @end+duration, @fixed)
|
81
|
+
else
|
82
|
+
self.class.new(@begin-duration, @end, @fixed)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Shortens the Interval by duration towards from the fixed end
|
87
|
+
# will raise if self < duration
|
88
|
+
def -(duration)
|
89
|
+
if @fixed == :begin then
|
90
|
+
self.class.new(@begin, @end-duration, @fixed)
|
91
|
+
else
|
92
|
+
self.class.new(@begin+duration, @end, @fixed)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# The number of picoseconds
|
97
|
+
def picoseconds
|
98
|
+
@duration.picoseconds
|
99
|
+
end
|
100
|
+
|
101
|
+
def days
|
102
|
+
@duration.days
|
103
|
+
end
|
104
|
+
|
105
|
+
def values_at(*keys)
|
106
|
+
to_hash.values_at(*keys)
|
107
|
+
end
|
108
|
+
|
109
|
+
# converts this interval to a duration
|
110
|
+
# if you set as_seconds to true it will convert the
|
111
|
+
# month primitive to seconds and use that
|
112
|
+
def to_duration
|
113
|
+
@duration
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_hash
|
117
|
+
@duration.to_hash.merge(:begin => @begin, :end => @end, :language => @language)
|
118
|
+
end
|
119
|
+
|
120
|
+
def format(string)
|
121
|
+
raise NoMethodError
|
122
|
+
end
|
123
|
+
|
124
|
+
def inspect
|
125
|
+
if @fixed == :begin then
|
126
|
+
sprintf InspectFixedBegin, self.class, @begin, @end, @duration
|
127
|
+
else
|
128
|
+
sprintf InspectFixedEnd, self.class, @begin, @end, @duration
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007-2008 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Chronos
|
10
|
+
class Interval
|
11
|
+
|
12
|
+
# A Gregorian Interval extens Interval by months.
|
13
|
+
# Unlike in Gregorian Durations, months exactly defined in seconds (and therefore minutes,
|
14
|
+
# hours, days, weeks).
|
15
|
+
# Internally a gregorian interval is stored as total picoseconds after days + days between the
|
16
|
+
# two dates and additionally the months + days after months + picoseconds after days. For
|
17
|
+
class Gregorian < Interval
|
18
|
+
ValidFixed = [:begin, :end].freeze
|
19
|
+
|
20
|
+
# The smaller of the two datetimes
|
21
|
+
attr_reader :begin
|
22
|
+
|
23
|
+
# The bigger of the two datetimes
|
24
|
+
attr_reader :end
|
25
|
+
|
26
|
+
# Which end is fixed, plays a role when adding, subtracting, multiplying, dividing, ...
|
27
|
+
attr_reader :fixed
|
28
|
+
|
29
|
+
# unlike new, between always creates a positive interval
|
30
|
+
# it will switch limit_a and limit_b if limit_a > limit_b
|
31
|
+
# it always fixates :begin
|
32
|
+
def self.between(limit_a, limit_b)
|
33
|
+
limit_a > limit_b ? new(limit_b, limit_a, false, :begin) : new(limit_a, limit_b, false, :begin)
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(limit_a, limit_b, fixed=nil)
|
37
|
+
super(limit_a, limit_b, fixed)
|
38
|
+
picoseconds = @end.ps_number - @begin.ps_number if @begin.time?
|
39
|
+
days, picoseconds = *picoseconds.divmod(PS_IN_DAY) if @begin.time?
|
40
|
+
months = 0
|
41
|
+
|
42
|
+
if @begin.date? then
|
43
|
+
a = Datetime.new(@begin.day_number, @begin.ps_number, ::Chronos::UTC)
|
44
|
+
b = Datetime.new(@end.day_number, @end.ps_number, ::Chronos::UTC)
|
45
|
+
days_after_months = days+b.day_of_month-a.day_of_month
|
46
|
+
months = b.year*12+b.month-a.year*12-a.month
|
47
|
+
|
48
|
+
# move 1 month forward
|
49
|
+
if days_after_months < 0 then
|
50
|
+
days_after_months += a.days_in_month
|
51
|
+
months -= 1
|
52
|
+
end
|
53
|
+
|
54
|
+
days += b.day_number - a.day_number
|
55
|
+
bsd = a.day_of_month > b.day_of_month ||
|
56
|
+
(start_date.time? && a.day_of_month == b.day_of_month && seconds < 0)
|
57
|
+
month1 = a.year*12+a.month+(bsd ? 1 : 0)
|
58
|
+
month2 = b.year*12+b.month
|
59
|
+
months = month2 - month1
|
60
|
+
a2y,a2m = *(month1-1).divmod(12)
|
61
|
+
a, b = Datetime.civil(a2y, a2m+1, 1), Datetime.civil(b.year, b.month, 1)
|
62
|
+
|
63
|
+
seconds_in_months = (b.day_number-a.day_number)*86400
|
64
|
+
p [seconds, seconds_in_months]
|
65
|
+
seconds -= seconds_in_months
|
66
|
+
|
67
|
+
b2y,b2m = *(month1+(months.div(12)*12)).divmod(12)
|
68
|
+
b = Datetime.civil(b2y, b2m+1, 1)
|
69
|
+
seconds_in_years = (b.day_number-a.day_number)*86400
|
70
|
+
end
|
71
|
+
|
72
|
+
@gregorian_duration = Duration::Gregorian.new(months, days+overflow, picoseconds, @language)
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_gregorian_duration
|
76
|
+
@gregorian_duration
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# 21. 12. 1982
|
2
|
+
# 21.12.1982
|
3
|
+
# 21. Dezember 1982
|
4
|
+
# 23:15 Uhr
|
5
|
+
# 23.15 Uhr
|
6
|
+
|
7
|
+
add(/#{day}\. ?#{month}\. ?#{year}/, :day, :month, :year)
|
8
|
+
add(/#{day}\. #{monthname} #{year}/, :day, :month, :year)
|
9
|
+
add(/#{hour}(?:[:.]#{minute}(?:[:.]#{second})?)?/, :hour, :minute, :second)
|
10
|
+
add(/gestern/) {
|
11
|
+
d = Chronos::Datetime::Gregorian.today
|
12
|
+
s = Chronos::Duration::Gregorian.new :days => 1
|
13
|
+
d.to_hash(:year, :month, :day)
|
14
|
+
}
|
15
|
+
add(/heute/) {
|
16
|
+
d = Chronos::Datetime::Gregorian.yesterday; d.to_hash(:year, :month, :day)
|
17
|
+
}
|
18
|
+
'#(gestern)#':
|
19
|
+
- yesterday
|
20
|
+
'#(heute)#':
|
21
|
+
- today
|
22
|
+
'#(morgen)#':
|
23
|
+
- tomorrow
|
24
|
+
'#(jetzt)#':
|
25
|
+
- now
|
26
|
+
'#(\d{1,2})\.(\d{1,2})\.(\d{4}|\d{2})?#':
|
27
|
+
- d
|
28
|
+
- m
|
29
|
+
- y
|
30
|
+
'#(\d{1,2})\. (\d{1,2})\. (\d{4}|\d{2}(?![.:]))?#':
|
31
|
+
- d
|
32
|
+
- m
|
33
|
+
- y
|
34
|
+
'#(\d{1,2})\. (\w{3,})\.? ?(\d{4}|\d{2})?#':
|
35
|
+
- d
|
36
|
+
- T
|
37
|
+
- y
|
38
|
+
'#(\d{1,2})\:(\d{1,2})h?#':
|
39
|
+
- H
|
40
|
+
- M
|
41
|
+
'#(\d{1,2})\:(\d{1,2})(h| uhr)?#':
|
42
|
+
- H
|
43
|
+
- M
|
44
|
+
'#(?:\A|[^\.\d])(\d{1,2})\.(\d{1,2})(?![\.\d])(h| uhr)?#':
|
45
|
+
- H
|
46
|
+
- M
|
47
|
+
- 0
|
48
|
+
'#(\d{1,2})(h| uhr)#':
|
49
|
+
- H
|
50
|
+
- 0
|
@@ -0,0 +1 @@
|
|
1
|
+
add_format "%m/%d/%Y"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
add_format_as "Y", /(\d{4})/, :year # 4 digits
|
2
|
+
add_format_as "m", /(0?[1-9]|1[012])/, :month # 1-12 with optional leading zero
|
3
|
+
add_format_as "d", /(0?[1-9]|[12]\d|3[01])/, :day_of_month # 1-31 with optional leading zero
|
4
|
+
add_format_as "H", /([01]?\d|2[123])/, :hour # 0-23 with optional leading zero
|
5
|
+
add_format_as "M", /([0-5]?\d)/, :minute # 0-59 with optional leading zero
|
6
|
+
add_format_as "S", /([0-5]?\d|60)/, :second # 0-60 with optional leading zero (leap second)
|
7
|
+
add_format_as "Z", /(#{Chronos::TimezonesByName.keys.sort.join('|')})/, :timezone do |parser, matches| # timezones are known to have no special chars, no escaping required
|
8
|
+
if tz = Chronos::TimezonesByName[matches.first] then
|
9
|
+
tz.offset
|
10
|
+
end
|
11
|
+
end
|
12
|
+
add_format_as "z", /(+-)/, :timezone do |parser, matches| # timezones are known to have no special chars, no escaping required
|
13
|
+
if tz = Chronos::TimezonesByName[matches.first] then
|
14
|
+
tz.offset
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
add_format_as "iso_date", /#{Y}-(#{m})-#{d}/, :year, :month, :day
|
19
|
+
add_format_as
|
20
|
+
|
21
|
+
add_format(/#{iso_date}/)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
---
|
2
|
+
:monthname:
|
3
|
+
- Januar
|
4
|
+
- Februar
|
5
|
+
- März
|
6
|
+
- April
|
7
|
+
- Mai
|
8
|
+
- Juni
|
9
|
+
- Juli
|
10
|
+
- August
|
11
|
+
- September
|
12
|
+
- Oktober
|
13
|
+
- November
|
14
|
+
- Dezember
|
15
|
+
:monthnameshort:
|
16
|
+
- Jan
|
17
|
+
- Feb
|
18
|
+
- Mär
|
19
|
+
- Apr
|
20
|
+
- Mai
|
21
|
+
- Jun
|
22
|
+
- Jul
|
23
|
+
- Aug
|
24
|
+
- Sep
|
25
|
+
- Okt
|
26
|
+
- Nov
|
27
|
+
- Dez
|
28
|
+
:dayname:
|
29
|
+
- Montag
|
30
|
+
- Dienstag
|
31
|
+
- Mittwoch
|
32
|
+
- Donnerstag
|
33
|
+
- Freitag
|
34
|
+
- Samstag
|
35
|
+
- Sonntag
|
36
|
+
:daynameshort:
|
37
|
+
- Mo
|
38
|
+
- Di
|
39
|
+
- Mi
|
40
|
+
- Do
|
41
|
+
- Fr
|
42
|
+
- Sa
|
43
|
+
- So
|
44
|
+
:picosecond:
|
45
|
+
~: Picosekunden
|
46
|
+
1: Picosekunde
|
47
|
+
:nanosecond:
|
48
|
+
~: Nanosekunden
|
49
|
+
1: Nanosekunde
|
50
|
+
:microsecond:
|
51
|
+
~: Mikrosekunden
|
52
|
+
1: Mikrosekunde
|
53
|
+
:millisecond:
|
54
|
+
~: Millisekunden
|
55
|
+
1: Millisekunde
|
56
|
+
:second:
|
57
|
+
~: Sekunden
|
58
|
+
1: Sekunde
|
59
|
+
:minute:
|
60
|
+
~: Minuten
|
61
|
+
1: Minute
|
62
|
+
:hour:
|
63
|
+
~: Stunden
|
64
|
+
1: Stunde
|
65
|
+
:day:
|
66
|
+
~: Tage
|
67
|
+
1: Tag
|
68
|
+
:week:
|
69
|
+
~: Wochen
|
70
|
+
1: Woche
|
71
|
+
:month:
|
72
|
+
~: Monate
|
73
|
+
1: Monat
|
74
|
+
:year:
|
75
|
+
~: Jahre
|
76
|
+
1: Jahr
|
@@ -0,0 +1,76 @@
|
|
1
|
+
---
|
2
|
+
:monthname:
|
3
|
+
- january
|
4
|
+
- february
|
5
|
+
- march
|
6
|
+
- april
|
7
|
+
- may
|
8
|
+
- june
|
9
|
+
- july
|
10
|
+
- august
|
11
|
+
- september
|
12
|
+
- october
|
13
|
+
- november
|
14
|
+
- december
|
15
|
+
:monthnameshort:
|
16
|
+
- jan
|
17
|
+
- feb
|
18
|
+
- mar
|
19
|
+
- apr
|
20
|
+
- may
|
21
|
+
- jun
|
22
|
+
- jul
|
23
|
+
- aug
|
24
|
+
- sep
|
25
|
+
- oct
|
26
|
+
- nov
|
27
|
+
- dec
|
28
|
+
:dayname:
|
29
|
+
- monday
|
30
|
+
- tuesday
|
31
|
+
- wednesday
|
32
|
+
- thursday
|
33
|
+
- friday
|
34
|
+
- saturday
|
35
|
+
- sunday
|
36
|
+
:daynameshort:
|
37
|
+
- mo
|
38
|
+
- tu
|
39
|
+
- we
|
40
|
+
- th
|
41
|
+
- fr
|
42
|
+
- sa
|
43
|
+
- su
|
44
|
+
:picosecond:
|
45
|
+
~: picoseconds
|
46
|
+
1: picosecond
|
47
|
+
:nanosecond:
|
48
|
+
~: nanoseconds
|
49
|
+
1: nanosecond
|
50
|
+
:microsecond:
|
51
|
+
~: microseconds
|
52
|
+
1: microsecond
|
53
|
+
:millisecond:
|
54
|
+
~: milliseconds
|
55
|
+
1: millisecond
|
56
|
+
:second:
|
57
|
+
~: seconds
|
58
|
+
1: second
|
59
|
+
:minute:
|
60
|
+
~: minutes
|
61
|
+
1: minute
|
62
|
+
:hour:
|
63
|
+
~: hours
|
64
|
+
1: hour
|
65
|
+
:day:
|
66
|
+
~: days
|
67
|
+
1: day
|
68
|
+
:week:
|
69
|
+
~: weeks
|
70
|
+
1: week
|
71
|
+
:month:
|
72
|
+
~: months
|
73
|
+
1: month
|
74
|
+
:year:
|
75
|
+
~: years
|
76
|
+
1: year
|