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.
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