vremya 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+