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,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)