chronos 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG.rdoc +27 -0
  2. data/HISTORY.rdoc +4 -0
  3. data/LICENSE.txt +52 -0
  4. data/MANIFEST.txt +51 -0
  5. data/NOTES.rdoc +85 -0
  6. data/README.rdoc +125 -0
  7. data/Rakefile +34 -0
  8. data/TODO.rdoc +63 -0
  9. data/bench/completebench.rb +24 -0
  10. data/ext/cchronos/extconf.rb +5 -0
  11. data/ext/chronos_core/extconf.rb +5 -0
  12. data/lib/chronos.rb +208 -0
  13. data/lib/chronos/calendar.rb +16 -0
  14. data/lib/chronos/calendar/gregorian.rb +94 -0
  15. data/lib/chronos/data/zones.tab +424 -0
  16. data/lib/chronos/datetime.rb +299 -0
  17. data/lib/chronos/datetime/gregorian.rb +698 -0
  18. data/lib/chronos/duration.rb +141 -0
  19. data/lib/chronos/duration/gregorian.rb +261 -0
  20. data/lib/chronos/durationtotext.rb +42 -0
  21. data/lib/chronos/exceptions.rb +16 -0
  22. data/lib/chronos/gregorian.rb +27 -0
  23. data/lib/chronos/interval.rb +132 -0
  24. data/lib/chronos/interval/gregorian.rb +80 -0
  25. data/lib/chronos/locale/parsers/de_CH.rb +50 -0
  26. data/lib/chronos/locale/parsers/en_US.rb +1 -0
  27. data/lib/chronos/locale/parsers/generic.rb +21 -0
  28. data/lib/chronos/locale/strings/de_DE.yaml +76 -0
  29. data/lib/chronos/locale/strings/en_US.yaml +76 -0
  30. data/lib/chronos/minimalistic.rb +37 -0
  31. data/lib/chronos/numeric/gregorian.rb +100 -0
  32. data/lib/chronos/ruby.rb +6 -0
  33. data/lib/chronos/version.rb +21 -0
  34. data/lib/chronos/zone.rb +212 -0
  35. data/rake/initialize.rb +116 -0
  36. data/rake/lib/assesscode.rb +59 -0
  37. data/rake/lib/bonesplitter.rb +245 -0
  38. data/rake/lib/projectclass.rb +69 -0
  39. data/rake/tasks/copyright.rake +24 -0
  40. data/rake/tasks/gem.rake +119 -0
  41. data/rake/tasks/git.rake +40 -0
  42. data/rake/tasks/loc.rake +33 -0
  43. data/rake/tasks/manifest.rake +63 -0
  44. data/rake/tasks/meta.rake +16 -0
  45. data/rake/tasks/notes.rake +36 -0
  46. data/rake/tasks/post_load.rake +18 -0
  47. data/rake/tasks/rdoc.rake +73 -0
  48. data/rake/tasks/rubyforge.rake +67 -0
  49. data/rake/tasks/spec.rake +55 -0
  50. data/spec/bacon_helper.rb +43 -0
  51. data/spec/lib/chronos/datetime/gregorian_spec.rb +314 -0
  52. data/spec/lib/chronos/datetime_spec.rb +219 -0
  53. data/spec/lib/chronos_spec.rb +91 -0
  54. 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