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,37 @@
1
+ #--
2
+ # Copyright 2007-2008 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'chronos/datetime'
10
+
11
+
12
+
13
+
14
+ module Chronos
15
+ module Datetime
16
+ module Gregorian
17
+
18
+ # require 'chronos/minimalistic' for 'y' method.
19
+ alias y year
20
+
21
+ # require 'chronos/minimalistic' for 'm' method.
22
+ alias m month
23
+
24
+ # require 'chronos/minimalistic' for 'd' method.
25
+ alias d day_of_month
26
+
27
+ # require 'chronos/minimalistic' for 'H' method.
28
+ alias H hour
29
+
30
+ # require 'chronos/minimalistic' for 'M' method.
31
+ alias M minute
32
+
33
+ # require 'chronos/minimalistic' for 'S' method.
34
+ alias S s
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,100 @@
1
+ #--
2
+ # Copyright 2007-2008 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'chronos/duration/gregorian'
10
+
11
+
12
+
13
+ module Chronos
14
+ module Numeric
15
+ module Gregorian
16
+
17
+ # Get a duration of the receivers amount of picoseconds
18
+ def picoseconds(language)
19
+ ::Chronos::Duration::Gregorian.new(0, 0, self, 0, language)
20
+ end
21
+ alias picosecond picoseconds
22
+
23
+ # Get a duration of the receivers amount of nanoseconds
24
+ def nanoseconds(language)
25
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_NANOSECOND, language)
26
+ end
27
+ alias nanosecond nanoseconds
28
+
29
+ # Get a duration of the receivers amount of microseconds
30
+ def microseconds(language)
31
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_MICROSECOND, language)
32
+ end
33
+ alias microsecond microseconds
34
+
35
+ # Get a duration of the receivers amount of milliseconds
36
+ def milliseconds(language)
37
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_MILLISECOND, language)
38
+ end
39
+ alias millisecond milliseconds
40
+
41
+ # Get a duration of the receivers amount of seconds
42
+ def seconds(language)
43
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_SECOND, language)
44
+ end
45
+ alias second seconds
46
+
47
+ # Get a duration of the receivers amount of minutes
48
+ def minutes(language)
49
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_MINUTE, language)
50
+ end
51
+ alias minute minutes
52
+
53
+ # Get a duration of the receivers amount of hours
54
+ def hours(language)
55
+ ::Chronos::Duration::Gregorian.new(0, 0, self*::Chronos::PS_IN_HOUR, language)
56
+ end
57
+ alias hour hours
58
+
59
+ # Get a duration of the receivers amount of days
60
+ def days(language)
61
+ ::Chronos::Duration::Gregorian.new(0, self, 0, language)
62
+ end
63
+ alias day days
64
+
65
+ # Get a duration of the receivers amount of weeks
66
+ def weeks(language)
67
+ ::Chronos::Duration::Gregorian.new(0, self*7, 0, language)
68
+ end
69
+ alias week weeks
70
+
71
+ # Get a duration of the receivers amount of months
72
+ def months(language)
73
+ ::Chronos::Duration::Gregorian.new(self, 0, 0, language)
74
+ end
75
+ alias month months
76
+
77
+ # Get a duration of the receivers amount of years
78
+ def years(language)
79
+ ::Chronos::Duration::Gregorian.new(self*12, 0, 0, language)
80
+ end
81
+ alias year years
82
+
83
+ # Get a duration of the receivers amount of decades
84
+ def decades(language)
85
+ ::Chronos::Duration::Gregorian.new(self*144, 0, 0, language)
86
+ end
87
+ alias decade decades
88
+
89
+ # Get a duration of the receivers amount of centuries
90
+ def centuries(language)
91
+ ::Chronos::Duration::Gregorian.new(self*1200, 0, 0, language)
92
+ end
93
+ alias century centuries
94
+ end
95
+ end
96
+ end
97
+
98
+ class Numeric
99
+ include Chronos::Numeric::Gregorian
100
+ end
@@ -0,0 +1,6 @@
1
+ class Integer
2
+ # whether the given number is a leap year in gregorian calendar system
3
+ def leap_year?
4
+ ((self%4).zero? && !(self%100).zero?) || (self%400).zero?
5
+ end
6
+ end
@@ -0,0 +1,21 @@
1
+ #--
2
+ # Copyright 2007-2008 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ begin; require 'rubygems'; rescue LoadError; end
10
+
11
+
12
+
13
+ module Chronos
14
+ version = '0.1.0'.freeze
15
+
16
+ if Object.const_defined?(:Gem) && Gem.const_defined?(:Version) then
17
+ VERSION = Gem::Version.new(version)
18
+ else
19
+ VERSION = version
20
+ end
21
+ end
@@ -0,0 +1,212 @@
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
+ Zone = Struct.new(
11
+ :timezone_id,
12
+ :language,
13
+ :utc,
14
+ :offset,
15
+ :dstrule,
16
+ :numeric,
17
+ :alpha2,
18
+ :alpha3,
19
+ :country,
20
+ :latitude,
21
+ :longitude,
22
+ :latitude_iso,
23
+ :longitude_iso
24
+ )
25
+ class Zone
26
+ Inspect = "#<%s:%s>"
27
+
28
+ @by_name = {}
29
+ @by_region = {}
30
+
31
+ # the UTC timezones, offset in seconds
32
+ # FIXME: as soon as rdoc stops sucking, use :'<name>' instead of '<name>'.to_sym
33
+ # (:stopdoc: proved useless, see earlier version in the git repo)
34
+ Offset = {
35
+ "UTC-12".to_sym => -43200, # I would love to use :'UTC-12', but rdoc fails with that
36
+ "UTC-11".to_sym => -39600,
37
+ "UTC-10".to_sym => -36000,
38
+ "UTC-9:30".to_sym => -34200,
39
+ "UTC-9".to_sym => -32400,
40
+ "UTC-8".to_sym => -28800,
41
+ "UTC-7".to_sym => -25200,
42
+ "UTC-6".to_sym => -21600,
43
+ "UTC-5".to_sym => -18000,
44
+ "UTC-4:30".to_sym => -16200,
45
+ "UTC-4".to_sym => -14400,
46
+ "UTC-3:30".to_sym => -12600,
47
+ "UTC-3".to_sym => -10800,
48
+ "UTC-2".to_sym => -7200,
49
+ "UTC-1".to_sym => -3600,
50
+ "UTC".to_sym => 0,
51
+ "UTC+1".to_sym => 3600,
52
+ "UTC+2".to_sym => 7200,
53
+ "UTC+3".to_sym => 10800,
54
+ "UTC+3:07".to_sym => 11224,
55
+ "UTC+3:30".to_sym => 12600,
56
+ "UTC+4".to_sym => 14400,
57
+ "UTC+4:30".to_sym => 16200,
58
+ "UTC+5".to_sym => 18000,
59
+ "UTC+5:30".to_sym => 19800,
60
+ "UTC+5:45".to_sym => 20700,
61
+ "UTC+6".to_sym => 21600,
62
+ "UTC+6:30".to_sym => 23400,
63
+ "UTC+7".to_sym => 25200,
64
+ "UTC+8".to_sym => 28800,
65
+ "UTC+8:45".to_sym => 31500,
66
+ "UTC+9".to_sym => 32400,
67
+ "UTC+9:30".to_sym => 34200,
68
+ "UTC+10".to_sym => 36000,
69
+ "UTC+10:30".to_sym => 37800,
70
+ "UTC+11".to_sym => 39600,
71
+ "UTC+11:30".to_sym => 41400,
72
+ "UTC+12".to_sym => 43200,
73
+ "UTC+12:45".to_sym => 45900,
74
+ "UTC+13".to_sym => 46800,
75
+ "UTC+14".to_sym => 50400,
76
+ }
77
+
78
+ # map old/military timezone names to UTC
79
+ # corresponding utc, isDST[BOOL]
80
+ Map = Hash.new { |hash, key| key }.merge!({
81
+ # for ::DateTime
82
+ '-12:00' => ['utc-12', false],
83
+ '-11:00' => ['utc-11', false],
84
+ '-10:00' => ['utc-10', false],
85
+ '-09:00' => ['utc-9', false],
86
+ '-08:00' => ['utc-8', false],
87
+ '-07:00' => ['utc-7', false],
88
+ '-06:00' => ['utc-6', false],
89
+ '-05:00' => ['utc-5', false],
90
+ '-04:30' => ['utc-4:30', false],
91
+ '-04:00' => ['utc-4', false],
92
+ '-03:00' => ['utc-3', false],
93
+ '-03:30' => ['utc-3:30', false],
94
+ '-02:00' => ['utc-2', false],
95
+ '-01:00' => ['utc-1', false],
96
+ '+00:00' => ['utc', false],
97
+ '+01:00' => ['utc+1', false],
98
+ '+02:00' => ['utc+2', false],
99
+ '+03:00' => ['utc+3', false],
100
+ '+03:30' => ['utc+3:30', false],
101
+ '+04:00' => ['utc+4', false],
102
+ '+05:00' => ['utc+5', false],
103
+ '+05:30' => ['utc+5:30', false],
104
+ '+06:00' => ['utc+6', false],
105
+ '+07:00' => ['utc+7', false],
106
+ '+08:00' => ['utc+8', false],
107
+ '+09:00' => ['utc+9', false],
108
+ '+09:30' => ['utc+9:30', false],
109
+ '+10:00' => ['utc+10', false],
110
+ '+11:00' => ['utc+11', false],
111
+ '+12:00' => ['utc+12', false],
112
+ # military & old
113
+ 'yankee' => ['utc-12', false],
114
+ 'xray' => ['utc-11', false],
115
+ 'hst' => ['utc-10', false],
116
+ 'whisky' => ['utc-10', false],
117
+ 'akst' => ['utc-9', false],
118
+ 'akdt' => ['utc-9', true],
119
+ 'ydt' => ['utc-9', true],
120
+ 'victor' => ['utc-9', false],
121
+ 'pst' => ['utc-8', false],
122
+ 'pdt' => ['utc-8', true],
123
+ 'uniform' => ['utc-8', false],
124
+ 'mst' => ['utc-7', false],
125
+ 'mdt' => ['utc-7', true],
126
+ 'tango' => ['utc-7', false],
127
+ 'cst' => ['utc-6', false],
128
+ 'cdt' => ['utc-6', true],
129
+ 'sierra' => ['utc-6', false],
130
+ 'est' => ['utc-5', false],
131
+ 'edt' => ['utc-5', true],
132
+ 'romeo' => ['utc-5', false],
133
+ 'vst' => ['utc-4:30', false],
134
+ 'ast' => ['utc-4', false],
135
+ 'adt' => ['utc-4', true],
136
+ 'quebec' => ['utc-4', false],
137
+ 'nst' => ['utc-3:30', false],
138
+ 'ndt' => ['utc-3:30', true],
139
+ 'papa' => ['utc-3', false],
140
+ 'oscar' => ['utc-2', false],
141
+ 'november' => ['utc-1', false],
142
+ 'gmt' => ['utc', false],
143
+ 'wet' => ['utc', false],
144
+ 'zulu' => ['utc', false],
145
+ 'cet' => ['utc+1', false],
146
+ 'cest' => ['utc+1', true],
147
+ 'alpha' => ['utc+1', false],
148
+ 'bravo' => ['utc+2', false],
149
+ 'msk' => ['utc+3', false],
150
+ 'charlie' => ['utc+3', false],
151
+ 'delta' => ['utc+4', false],
152
+ 'echo' => ['utc+5', false],
153
+ 'ist' => ['utc+5:30', false],
154
+ 'foxtrot' => ['utc+6', false],
155
+ 'golf' => ['utc+7', false],
156
+ 'awst' => ['utc+8', false],
157
+ 'hotel' => ['utc+8', false],
158
+ 'india' => ['utc+9', false],
159
+ 'acst' => ['utc+9:30', false],
160
+ 'aest' => ['utc+10', false],
161
+ 'kilo' => ['utc+10', false],
162
+ 'lima' => ['utc+11', false],
163
+ 'mike' => ['utc+12', false]
164
+ })
165
+
166
+ # load locations from a tabfile
167
+ def self.load(tabfile, marshalfile=nil, marshal=true)
168
+ if marshalfile && File.readable?(marshalfile) && File.mtime(tabfile) <= File.mtime(marshalfile) then
169
+ @by_name.update(Marshal.load(File.read(marshalfile)))
170
+ else
171
+ data = {}
172
+ File.foreach(tabfile) { |line|
173
+ next if line[0] == ?#
174
+ tmp = line.chomp.split("\t")
175
+ tmp[3,0] = 0
176
+ location = new(*tmp)
177
+ location.utc = location.utc.to_sym
178
+ location.offset = Offset[location.utc]
179
+ location.numeric = Integer(location.numeric) rescue nil
180
+ location.latitude = Float(location.latitude) rescue nil
181
+ location.longitude = Float(location.longitude) rescue nil
182
+ location.latitude_iso = Integer(location.latitude_iso) rescue nil
183
+ location.longitude_iso = Integer(location.longitude_iso) rescue nil
184
+ data[location.timezone_id.downcase] = location
185
+ }
186
+ @by_name.update(data)
187
+ if marshalfile && marshal then
188
+ File.open(marshalfile, "wb") { |fh|
189
+ fh.write(Marshal.dump(data))
190
+ }
191
+ end
192
+ end
193
+ end
194
+
195
+ def self.[](name)
196
+ name = name.to_s.downcase
197
+ if zone = @by_name[name] then
198
+ zone
199
+ elsif mapped = Map[name]
200
+ @by_name[mapped.first]
201
+ end
202
+ end
203
+
204
+ def zone_names
205
+ @by_name.keys
206
+ end
207
+
208
+ def inspect
209
+ sprintf Inspect, self.class, timezone_id
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,116 @@
1
+ #--
2
+ # Copyright 2007-2008 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'pp'
10
+ $LOAD_PATH.unshift(File.expand_path("#{__FILE__}/../../lib")) # trunk/lib
11
+ $LOAD_PATH.unshift(File.expand_path("#{__FILE__}/../lib")) # trunk/rake/lib
12
+
13
+ begin; require 'rubygems'; rescue LoadError; end
14
+ require 'projectclass'
15
+ require 'bonesplitter'
16
+
17
+ include BoneSplitter
18
+
19
+ REQUIRED_RAKE_VERSION = "0.8"
20
+ abort("Requires rake version #{REQUIRED_RAKE_VERSION}") unless has_version?(RAKEVERSION, REQUIRED_RAKE_VERSION)
21
+
22
+ # bonesplitter requires a Markdown constant
23
+ unless lib?('markdown') then
24
+ if lib?('rdiscount') then
25
+ Markdown = RDiscount
26
+ has_lib!('markdown') # fake it
27
+ end
28
+ end
29
+
30
+ Project = ProjectClass.new
31
+
32
+ # Gem Packaging
33
+ Project.gem = ProjectClass.new({
34
+ :dependencies => nil,
35
+ :executables => nil,
36
+ :extensions => FileList['ext/**/extconf.rb'],
37
+ :files => nil,
38
+ :has_rdoc => true,
39
+ :need_tar => true,
40
+ :need_zip => false,
41
+ :extras => {},
42
+ })
43
+
44
+ # Data about the project itself
45
+ Project.meta = ProjectClass.new({
46
+ :name => nil,
47
+ :version => nil,
48
+ :author => "Stefan Rusterholz",
49
+ :email => "apeiros@gmx.net",
50
+ :summary => nil,
51
+ :website => nil,
52
+ :bugtracker => nil,
53
+ :feature_requests => nil,
54
+ :irc => "irc://freenode.org/#silverplatter",
55
+ :release_notes => "NEWS.rdoc",
56
+ :changelog => "CHANGELOG.rdoc",
57
+ :todo => "TODO.rdoc",
58
+ :readme => "README.rdoc",
59
+ :manifest => "MANIFEST.txt",
60
+ :gem_host => :rubyforge,
61
+ :configurations => "~/Library/Application Support/Bonesplitter",
62
+ })
63
+
64
+ # Manifest
65
+ Project.manifest = ProjectClass.new({
66
+ :include => %w[**/*],
67
+ :exclude => %w[dev/**/* docs/**/* pkg/**/* web/**/*],
68
+ })
69
+
70
+ # File Annotations
71
+ Project.notes = ProjectClass.new({
72
+ :include => %w[lib/**/*.rb {bin,ext}/**/*], # NOTE: use post_load and set to manifest()?
73
+ :exclude => %w[],
74
+ :tags => %w[FIXME OPTIMIZE TODO],
75
+ })
76
+
77
+ # Rcov
78
+ Project.rcov = ProjectClass.new({
79
+ :dir => 'coverage',
80
+ :opts => %w[--sort coverage -T],
81
+ :threshold => 100.0,
82
+ :threshold_exact => false,
83
+ })
84
+
85
+ # Rdoc
86
+ Project.rdoc = ProjectClass.new({
87
+ :options => %w[
88
+ --inline-source
89
+ --line-numbers
90
+ --charset utf-8
91
+ --tab-width 2
92
+ ],
93
+ :include => %w[{lib,bin,ext}/**/* *.{txt,markdown,rdoc}], # globs
94
+ :exclude => %w[**/*/extconf.rb Manifest.txt], # globs
95
+ :main => nil, # path
96
+ :output_dir => 'docs', # path
97
+ :remote_dir => 'irc/docs',
98
+ #:template => lib?(:allison) && Gem.searcher.find("allison").full_gem_path+"/lib/allison",
99
+ # 'Allison gem, tasks: doc:html, creates nicer html rdoc output'
100
+ })
101
+
102
+ # Rubyforge
103
+ Project.rubyforge = ProjectClass.new({
104
+ :project => nil, # The rubyforge projectname
105
+ })
106
+
107
+ # Specs (bacon)
108
+ Project.rubyforge = ProjectClass.new({
109
+ :files => FileList['spec/**/*_spec.rb'],
110
+ :opts => []
111
+ })
112
+
113
+ # Load the other rake files in the tasks folder
114
+ rakefiles = Dir.glob('rake/tasks/*.rake').sort
115
+ rakefiles.unshift(rakefiles.delete('rake/tasks/post_load.rake')).compact!
116
+ import(*rakefiles)