vremya 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 (5) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +3 -0
  3. data/Rakefile +17 -0
  4. data/lib/vremya.rb +509 -0
  5. metadata +102 -0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Merimond Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Vremya
2
+
3
+ A lump of syntactic sugar around native Date and Time objects, that takes the pain out of timezones, traversal, formatting etc.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'rspec/core/rake_task'
4
+ require 'yard'
5
+
6
+ Bundler.require
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ desc "Run specs"
10
+ RSpec::Core::RakeTask.new do |t|
11
+ # nothing
12
+ end
13
+
14
+ desc "Generate docs"
15
+ YARD::Rake::YardocTask.new do |t|
16
+ t.files = ['lib/**/*.rb']
17
+ end
data/lib/vremya.rb ADDED
@@ -0,0 +1,509 @@
1
+ require 'tzinfo'
2
+
3
+ class Vremya
4
+
5
+ SECONDS_IN_A_DAY = 60 * 60 * 24
6
+
7
+ def self.now(zone = nil)
8
+ self.new(Time.now.gmtime.to_i, zone)
9
+ end
10
+
11
+ def self.parse(string, format, timezone = nil)
12
+ self.new(DateTime.strptime(string, format)).as_if_in(timezone)
13
+ end
14
+
15
+ def self.timezones
16
+ TZInfo::Timezone.all_identifiers
17
+ end
18
+
19
+ # Returns a new Vremya object with the value given by time since the Epoch.
20
+ # @return [Vremya]
21
+ def initialize(timestamp, zone = nil)
22
+ if timestamp.is_a?(DateTime)
23
+ timestamp = timestamp.strftime("%s").to_i
24
+ end
25
+ unless timestamp.respond_to?(:to_i)
26
+ raise 'Timestamp expected, %s' % timestamp.class
27
+ end
28
+ @zone = TZInfo::Timezone.get(zone || 'GMT')
29
+ @stamp = timestamp.to_i
30
+ end
31
+
32
+ # Returns a new Vremya object where one or more of the elements have been
33
+ # changed according to the options parameter. The following options are
34
+ # available: :year, :month, :day, :hour, :minute, :second.
35
+ def change(options)
36
+ opts = to_hash.merge(options)
37
+ date = Date.new(opts[:year], opts[:month], opts[:day])
38
+ advance({
39
+ :days => (date - to_date).to_i,
40
+ :hours => opts[:hour] - hour,
41
+ :minutes => opts[:minute] - minute,
42
+ :seconds => opts[:second] - second
43
+ })
44
+ end
45
+
46
+ # Returns a new Vremya object by going forward or back in time according
47
+ # to the options parameter. The following options are available:
48
+ # :years, :months, :days, :hours, :minutes, :seconds.
49
+ def advance(options)
50
+ opts = {
51
+ :years => 0,
52
+ :months => 0,
53
+ :days => 0,
54
+ :hours => 0,
55
+ :minutes => 0,
56
+ :seconds => 0
57
+ }.merge(options)
58
+ date = to_date
59
+ date = date >> opts[:years] * 12
60
+ date = date >> opts[:months]
61
+ date = date + opts[:days]
62
+ diff = (date - to_date).to_i * 60 * 60 * 24
63
+ diff += opts[:hours] * 3600
64
+ diff += opts[:minutes] * 60
65
+ diff += opts[:seconds]
66
+ self + diff
67
+ end
68
+
69
+ # Returns same time and date one month ago. In cases where previous month
70
+ # doen't have the same date (e.g. Mar 30 -> Feb 30), it will go back to the
71
+ # last day of the month (Feb 29 or Feb 28).
72
+ # @return [Vremya]
73
+ def previous_month
74
+ advance(:months => -1)
75
+ end
76
+
77
+ alias_method :prev_month, :previous_month
78
+
79
+ # Returns same time and date last year.
80
+ # @return [Vremya]
81
+ def previous_year
82
+ advance(:years => -1)
83
+ end
84
+
85
+ alias_method :prev_year, :previous_year
86
+
87
+ # Goes back 24 hours and returns a new Vremya object.
88
+ # @return [Vremya]
89
+ def previous_day
90
+ advance(:days => -1)
91
+ end
92
+
93
+ alias_method :prev_day, :previous_day
94
+
95
+ # Returns same time and date next year.
96
+ # @return [Vremya]
97
+ def next_year
98
+ advance(:years => 1)
99
+ end
100
+
101
+ # Returns same time and date next month. In cases where next month
102
+ # doen't have the same date (e.g. Mar 31 -> Apr 31), it will advance to the
103
+ # last day of the month (Apr 30).
104
+ # @return [Vremya]
105
+ def next_month
106
+ advance(:months => 1)
107
+ end
108
+
109
+ # Advances by 24 hours and returns a new Vremya object.
110
+ # @return [Vremya]
111
+ def next_day
112
+ advance(:days => 1)
113
+ end
114
+
115
+ # Returns a new Vremya object representing the start of the day (00:00).
116
+ # @return [Vremya]
117
+ def beginning_of_day
118
+ change(:hour => 0, :minute => 0, :second => 0)
119
+ end
120
+
121
+ alias_method :at_beginning_of_day, :beginning_of_day
122
+ alias_method :midnight, :beginning_of_day
123
+ alias_method :at_midnight, :beginning_of_day
124
+
125
+ # Returns a new Time representing the "start" of this week (Monday, 0:00).
126
+ # @return [Vremya]
127
+ def beginning_of_week
128
+ advance(:days => wday == 0 ? -6 : 1 - wday)
129
+ end
130
+
131
+ alias_method :at_beginning_of_week, :beginning_of_week
132
+
133
+ # Returns a new Time representing the start of the month (1st of the month, 0:00).
134
+ # @return [Vremya]
135
+ def beginning_of_month
136
+ change(:day => 1, :hour => 0, :minute => 0, :second => 0)
137
+ end
138
+
139
+ alias_method :at_beginning_of_month, :beginning_of_month
140
+
141
+ # Returns a new Time representing the start of the year (1st of January, 0:00).
142
+ # @return [Vremya]
143
+ def beginning_of_year
144
+ change(:month => 1, :day => 1, :hour => 0, :minute => 0, :second => 0)
145
+ end
146
+
147
+ alias_method :at_beginning_of_year, :beginning_of_year
148
+
149
+ # Returns the second of the minute (0..60).
150
+ # @return [Fixnum]
151
+ def second
152
+ time_in_utc.sec
153
+ end
154
+
155
+ alias_method :sec, :second
156
+
157
+ # Returns the minute of the hour (0..59) for time.
158
+ # @return [Fixnum]
159
+ def minute
160
+ time_in_utc.min
161
+ end
162
+
163
+ alias_method :min, :minute
164
+
165
+ # Returns the hour of the day (0..23).
166
+ # @return [Fixnum]
167
+ def hour
168
+ time_in_utc.hour
169
+ end
170
+
171
+ # Returns the day of the month (1..n).
172
+ # @return [Fixnum]
173
+ def day
174
+ time_in_utc.day
175
+ end
176
+
177
+ # Returns the month of the year (1..12).
178
+ # @return [Fixnum]
179
+ def month
180
+ time_in_utc.month
181
+ end
182
+
183
+ # Returns the year (including the century).
184
+ # @return [Fixnum]
185
+ def year
186
+ time_in_utc.year
187
+ end
188
+
189
+ # Returns true if specified time lies in the future.
190
+ # @return [Boolean]
191
+ def future?
192
+ to_time > Time.now
193
+ end
194
+
195
+ # Returns true if specified time lies in the past.
196
+ # @return [Boolean]
197
+ def past?
198
+ to_time < Time.now
199
+ end
200
+
201
+ # Returns true if date represents January.
202
+ # @return [Boolean]
203
+ def january?
204
+ month == 1
205
+ end
206
+
207
+ alias_method :jan?, :january?
208
+
209
+ # Returns true if date represents February.
210
+ # @return [Boolean]
211
+ def february?
212
+ month == 2
213
+ end
214
+
215
+ alias_method :feb?, :february?
216
+
217
+ # Returns true if date represents March.
218
+ # @return [Boolean]
219
+ def march?
220
+ month == 3
221
+ end
222
+
223
+ alias_method :mar?, :march?
224
+
225
+ # Returns true if date represents April.
226
+ # @return [Boolean]
227
+ def april?
228
+ month == 4
229
+ end
230
+
231
+ alias_method :apr?, :april?
232
+
233
+ # Returns true if date represents May.
234
+ # @return [Boolean]
235
+ def may?
236
+ month == 5
237
+ end
238
+
239
+ # Returns true if date represents June.
240
+ # @return [Boolean]
241
+ def june?
242
+ month == 6
243
+ end
244
+
245
+ alias_method :jun?, :june?
246
+
247
+ # Returns true if date represents July.
248
+ # @return [Boolean]
249
+ def july?
250
+ month == 7
251
+ end
252
+
253
+ alias_method :jul?, :july?
254
+
255
+ # Returns true if date represents August.
256
+ # @return [Boolean]
257
+ def august?
258
+ month == 8
259
+ end
260
+
261
+ alias_method :aug?, :august?
262
+
263
+ # Returns true if date represents September.
264
+ # @return [Boolean]
265
+ def september?
266
+ month == 9
267
+ end
268
+
269
+ alias_method :sep?, :september?
270
+
271
+ # Returns true if date represents October.
272
+ # @return [Boolean]
273
+ def october?
274
+ month == 10
275
+ end
276
+
277
+ alias_method :oct?, :october?
278
+
279
+ # Returns true if date represents November.
280
+ # @return [Boolean]
281
+ def november?
282
+ month == 11
283
+ end
284
+
285
+ alias_method :nov?, :november?
286
+
287
+ # Returns true if date represents December.
288
+ # @return [Boolean]
289
+ def december?
290
+ month == 12
291
+ end
292
+
293
+ alias_method :dec?, :december?
294
+
295
+ # Returns true if time represents Monday.
296
+ # @return [Boolean]
297
+ def monday?
298
+ wday == 1
299
+ end
300
+
301
+ alias_method :mon?, :monday?
302
+
303
+ # Returns true if time represents Tuesday.
304
+ # @return [Boolean]
305
+ def tuesday?
306
+ wday == 2
307
+ end
308
+
309
+ alias_method :tue?, :tuesday?
310
+
311
+ # Returns true if time represents Wednesday.
312
+ # @return [Boolean]
313
+ def wednesday?
314
+ wday == 3
315
+ end
316
+
317
+ alias_method :wed?, :wednesday?
318
+
319
+ # Returns true if time represents Thursday.
320
+ # @return [Boolean]
321
+ def thursday?
322
+ wday == 4
323
+ end
324
+
325
+ alias_method :thu?, :thursday?
326
+
327
+ # Returns true if time represents Friday.
328
+ # @return [Boolean]
329
+ def friday?
330
+ wday == 5
331
+ end
332
+
333
+ alias_method :fri?, :friday?
334
+
335
+ # Returns true if time represents Saturday.
336
+ # @return [Boolean]
337
+ def saturday?
338
+ wday == 6
339
+ end
340
+
341
+ alias_method :sat?, :saturday?
342
+
343
+ # Returns true if time represents Sunday.
344
+ # @return [Boolean]
345
+ def sunday?
346
+ wday == 0
347
+ end
348
+
349
+ alias_method :sun?, :sunday?
350
+
351
+ # Returns true if time represents any day of the week except Sunday and Saturday.
352
+ # @return [Boolean]
353
+ def weekday?
354
+ not weekend?
355
+ end
356
+
357
+ # Returns true if time represents Sunday or Saturday.
358
+ # @return [Boolean]
359
+ def weekend?
360
+ saturday? or sunday?
361
+ end
362
+
363
+ # Returns an integer representing the day of the week, 0..6, with Sunday == 0.
364
+ # @return [Fixnum]
365
+ def wday
366
+ time_in_utc.wday
367
+ end
368
+
369
+ # Returns an integer representing the day of the week, 0..6. Similar to #wday, but assumes Monday == 0 and Sunday == 6.
370
+ def wday_starting_on_monday
371
+ sunday? ? 6 : wday - 1
372
+ end
373
+
374
+ # Returns true if daylight savings are in effect at this timezone.
375
+ # @return [Boolean]
376
+ def daylight_saving?
377
+ @zone.current_period.dst?
378
+ end
379
+
380
+ alias_method :dst?, :daylight_saving?
381
+
382
+ # Returns timezone identifier, e.g. "Europe/Paris"
383
+ # @return [String]
384
+ def timezone_name
385
+ @zone.name
386
+ end
387
+
388
+ # Returns the offset in seconds between the timezone of time and UTC.
389
+ # @return [Fixnum]
390
+ def utc_offset
391
+ @zone.current_period.utc_offset
392
+ end
393
+
394
+ # Returns a new Vremya object in GMT timezone.
395
+ # @return [Vremya]
396
+ def to_utc
397
+ self.class.new(to_i)
398
+ end
399
+
400
+ # Returns a new Vremya object in specified timezone.
401
+ # @return [Vremya]
402
+ def to_timezone(zone)
403
+ self.class.new(to_i, zone)
404
+ end
405
+
406
+ # Returns the difference with specified timezone in seconds.
407
+ # @return [Integer]
408
+ def difference_with_zone(zone)
409
+ to_timezone(zone).utc_offset - utc_offset
410
+ end
411
+
412
+ # Returns a new Vremya instance by advancing in time.
413
+ def as_if_in(zone)
414
+ to_timezone(zone) - difference_with_zone(zone)
415
+ end
416
+
417
+ # Substracts some number of seconds to time and returns that value as a new Vremya object.
418
+ # @return [Vremya]
419
+ def -(value)
420
+ self.+(-value)
421
+ end
422
+
423
+ # Adds some number of seconds to time and returns that value as a new Vremya object.
424
+ # @return [Vremya]
425
+ def +(value)
426
+ self.class.new(to_i + value, timezone_name)
427
+ end
428
+
429
+ # Returns the number of seconds since 1970-01-01 00:00:00 UTC.
430
+ # @return [Fixnum]
431
+ def to_i
432
+ @stamp
433
+ end
434
+
435
+ # Returns a native Ruby Time object in UTC timezone.
436
+ # @return [Time]
437
+ def to_time
438
+ Time.at(@stamp).getutc
439
+ end
440
+
441
+ # Returns a native Ruby Time object in UTC timezone.
442
+ # @return [Time]
443
+ def to_date
444
+ Date.new(year, month, day)
445
+ end
446
+
447
+ # Returns a string which represents the time as date-time defined by RFC 2616.
448
+ # @return [String]
449
+ def rfc2616
450
+ to_utc.strftime("%a, %e %b %Y %T GMT")
451
+ end
452
+
453
+ # Returns a string which represents the time as date-time defined by RFC 2822.
454
+ # @return [String]
455
+ def rfc2822
456
+ strftime("%a, %b %e %T %z %Y")
457
+ end
458
+
459
+ # Returns a string which represents the time as date-time defined by ISO 8601.
460
+ # @return [String]
461
+ def iso8601
462
+ strftime("%Y-%m-%dT%H:%M:%S%z")
463
+ end
464
+
465
+ # Returns a string representing time.
466
+ # @return [String]
467
+ def to_s
468
+ strftime("%a %b %d %T %z %Y")
469
+ end
470
+
471
+ # Returns a hash with time & date attributes.
472
+ # @return [Hash]
473
+ def to_hash
474
+ { :year => year, :month => month, :day => day, :hour => hour, :minute => minute, :second => second }
475
+ end
476
+
477
+ # Returns a string which represents the time as date-time defined by ISO 8601.
478
+ # @return [String]
479
+ def as_yaml(*args)
480
+ iso8601
481
+ end
482
+
483
+ # Returns a YAML representation of the instance.
484
+ # @return [String]
485
+ def to_yaml
486
+ as_yaml.to_yaml
487
+ end
488
+
489
+ # Returns time as a string according to the given format. The formatting is identical to Time.strftime
490
+ # @return [String]
491
+ def strftime(string)
492
+ @zone.strftime string.gsub(/%z/, utc_offset_as_string), to_time
493
+ end
494
+
495
+ private
496
+
497
+ def utc_offset_as_string
498
+ "%s%s" % [utc_offset < 0 ? '-' : '+', formatted_hours(utc_offset)]
499
+ end
500
+
501
+ def formatted_hours(seconds)
502
+ "%02d:%02d" % (seconds / 60).divmod(60)
503
+ end
504
+
505
+ def time_in_utc
506
+ to_time + utc_offset
507
+ end
508
+
509
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vremya
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ version: "1.0"
9
+ platform: ruby
10
+ authors:
11
+ - Alex Serebryakov
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2013-10-08 00:00:00 +04:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ type: :development
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ segments:
26
+ - 0
27
+ version: "0"
28
+ name: rspec
29
+ requirement: *id001
30
+ prerelease: false
31
+ - !ruby/object:Gem::Dependency
32
+ type: :development
33
+ version_requirements: &id002 !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ segments:
38
+ - 0
39
+ version: "0"
40
+ name: yard
41
+ requirement: *id002
42
+ prerelease: false
43
+ - !ruby/object:Gem::Dependency
44
+ type: :runtime
45
+ version_requirements: &id003 !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ segments:
50
+ - 0
51
+ - 3
52
+ - 37
53
+ version: 0.3.37
54
+ name: tzinfo
55
+ requirement: *id003
56
+ prerelease: false
57
+ description: "A lump of syntactic sugar around native Date and Time objects, that takes the pain out of timezones, traversal, formatting etc. "
58
+ email:
59
+ - alex@merimond.com
60
+ executables: []
61
+
62
+ extensions: []
63
+
64
+ extra_rdoc_files: []
65
+
66
+ files:
67
+ - lib/vremya.rb
68
+ - Rakefile
69
+ - README.md
70
+ - LICENSE
71
+ has_rdoc: true
72
+ homepage: https://github.com/merimond/vremya
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirements: []
95
+
96
+ rubyforge_project: vremya
97
+ rubygems_version: 1.3.6
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Time & date library for Ruby
101
+ test_files: []
102
+