date_time_attribute 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +19 -0
- data/.travis.yml +4 -0
- data/Gemfile +9 -0
- data/README.md +128 -0
- data/Rakefile +5 -0
- data/date_time_attribute.gemspec +23 -0
- data/lib/date_time_attribute.rb +108 -0
- data/lib/date_time_attribute/container.rb +81 -0
- data/spec/date_time_attribute/container_spec.rb +105 -0
- data/spec/date_time_attribute_spec.rb +205 -0
- data/spec/spec_helper.rb +12 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZWNmMGZkNmU3MjU3YmJlNmY5M2Y1OTE4ZTcxNjYxYjJjYzhjYzRmNQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ODIyYTdjYzg0NTEyZWRlYWY1NGJkOTNiNWEyNWZjNzIyYjRiMzgyNw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YmFiMjNhNjIyYTcwOTJmNmZiYzQwY2E5OGI4ZjFjMzdhYmQ0NTkzYzllY2Ey
|
10
|
+
MWRiYjYxYjZlZDUzNjc4YmM0MjUzZDQ3MzY0NmQxNjg1ZjQ3MTAzZTViOThk
|
11
|
+
NmRjZjdkZTg0OGEwYjk4ZmYyYWQwNDYxMWU4YTZkZGU0ODY2NDk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YmU4NjQxNDIzYjMxNDQzODZmYmI2MTRkZjY3NjQzYTE5NWI4NzQ3MTZiODM0
|
14
|
+
ZTIyNzE3ZTI5ZjJiNzBkYTRlNjNlNDg1NTE2N2I4ZDc2MjM4MTFlMTdkNDYz
|
15
|
+
NjU5NDVmNGEwMjc4NTFkYjJlNWU5YTQ5YTRlY2U3ZmRmNDkxZGM=
|
data/.coveralls.yml
ADDED
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# DateTime attribute for Ruby!
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/date_time_attribute.png)](http://badge.fury.io/rb/date_time_attribute)
|
3
|
+
[![Build Status](https://travis-ci.org/einzige/date_time_attribute.png?branch=master)](https://travis-ci.org/einzige/date_time_attribute)
|
4
|
+
[![Dependency Status](https://gemnasium.com/einzige/date_time_attribute.png)](https://gemnasium.com/einzige/date_time_attribute)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/einzige/date_time_attribute/badge.png)](https://coveralls.io/r/einzige/date_time_attribute)
|
6
|
+
|
7
|
+
Splits DateTime attribute access into two Data, Time and TimeZone attributes.
|
8
|
+
|
9
|
+
See also [ActiveRecord (Rails) version](https://github.com/einzige/date_time_attribute_rails).
|
10
|
+
|
11
|
+
## Install
|
12
|
+
|
13
|
+
```bash
|
14
|
+
gem install date_time_attribute
|
15
|
+
```
|
16
|
+
|
17
|
+
## Enjoy
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'date_time_attribute'
|
21
|
+
|
22
|
+
class Task
|
23
|
+
include DateTimeAttribute
|
24
|
+
date_time_attribute :due_at
|
25
|
+
end
|
26
|
+
|
27
|
+
task = Task.new
|
28
|
+
task.due_at # => nil
|
29
|
+
|
30
|
+
# Date set
|
31
|
+
task.due_at_date = '2001-02-03'
|
32
|
+
task.due_at_date # => 2001-02-03 00:00:00 +0700
|
33
|
+
task.due_at_time # => 2001-02-03 00:00:00 +0700
|
34
|
+
task.due_at # => 2001-02-03 00:00:00 +0700
|
35
|
+
|
36
|
+
# Time set
|
37
|
+
task.due_at_time = '10:00pm'
|
38
|
+
task.due_at_time # => 2013-12-02 22:00:00 +0800
|
39
|
+
task.due_at_date # => 2001-02-03 00:00:00 +0700
|
40
|
+
task.due_at # => 2001-02-03 22:00:00 +0700
|
41
|
+
|
42
|
+
# Time zone is applied as set
|
43
|
+
task.due_at_time_zone = 'Moscow'
|
44
|
+
task.due_at # => Mon, 03 Feb 2013 22:00:00 MSK +04:00
|
45
|
+
task.due_at_time_zone = 'London'
|
46
|
+
task.due_at # => Mon, 03 Feb 2013 22:00:00 GMT +00:00
|
47
|
+
```
|
48
|
+
|
49
|
+
You can also use it with already existing/initialized attributes
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class Task
|
53
|
+
include DateTimeAttribute
|
54
|
+
|
55
|
+
attr_accessor :due_at
|
56
|
+
date_time_attribute :due_at
|
57
|
+
|
58
|
+
def initialize
|
59
|
+
self.due_at = Time.zone.now.tomorrow
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
## Using time zones
|
65
|
+
|
66
|
+
Default time zone can be applied to an attribute:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class Task
|
70
|
+
include DateTimeAttribute
|
71
|
+
date_time_attribute :due_at, time_zone: 'Moscow'
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class Task
|
77
|
+
include DateTimeAttribute
|
78
|
+
date_time_attribute :due_at, time_zone: Proc.new { 'Moscow' }
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class Task
|
84
|
+
include DateTimeAttribute
|
85
|
+
date_time_attribute :due_at, time_zone: :my_time_zone
|
86
|
+
|
87
|
+
def my_time_zone
|
88
|
+
self.in_da_moscow? ? 'Moscow' : 'Birobidgan'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
You can also explicitly set timezone:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Time.zone = 'Krasnoyarsk'
|
97
|
+
task.due_at # => nil
|
98
|
+
task.due_at_time = '02:00am'
|
99
|
+
task.due_at # => Mon, 02 Dec 2013 02:00:00 KRAT +08:00
|
100
|
+
task.due_at_time_zone = 'Moscow'
|
101
|
+
task.due_at # => Mon, 02 Dec 2013 02:00:00 MSK +04:00
|
102
|
+
```
|
103
|
+
|
104
|
+
## Using Chronic gem
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
DateTimeAttribute.parser = Chronic
|
108
|
+
|
109
|
+
task.due_at_date = 'next saturday'
|
110
|
+
task.due_at_time = '10:00pm'
|
111
|
+
```
|
112
|
+
|
113
|
+
## Advanced usage
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
my_date_time = DateTimeAttribute::Container.new
|
117
|
+
my_date_time.date_time # => nil
|
118
|
+
my_date_time.date = '2001-02-03'
|
119
|
+
my_date_time.date_time # => 2001-02-03 00:00:00 +0700
|
120
|
+
my_date_time.dime = '10:00pm'
|
121
|
+
my_date_time.date_time # => 2001-02-03 22:00:00 +0700
|
122
|
+
|
123
|
+
# ...same as described above
|
124
|
+
```
|
125
|
+
|
126
|
+
## See also
|
127
|
+
|
128
|
+
[ActiveRecord (Rails) version](https://github.com/einzige/date_time_attribute_rails)
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{date_time_attribute}
|
5
|
+
s.version = "0.0.4"
|
6
|
+
|
7
|
+
s.date = %q{2013-11-22}
|
8
|
+
s.authors = ["Sergei Zinin"]
|
9
|
+
s.email = %q{szinin@gmail.com}
|
10
|
+
s.homepage = %q{http://github.com/einzige/date_time_attribute}
|
11
|
+
|
12
|
+
s.licenses = ["MIT"]
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.extra_rdoc_files = ["README.md"]
|
17
|
+
|
18
|
+
s.description = %q{Allows to assign date and time attributes separately for a DateTime attribute in your model instance. Plays with time zones as well.}
|
19
|
+
s.summary = %q{Splits DateTime attribute access into three separate Data, Time and TimeZone attributes}
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'activesupport', ">= 3.0.0"
|
22
|
+
s.add_development_dependency 'bundler'
|
23
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/duration'
|
4
|
+
require 'date_time_attribute/container'
|
5
|
+
|
6
|
+
module DateTimeAttribute
|
7
|
+
VERSION = '0.0.4'
|
8
|
+
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
def self.parser
|
12
|
+
DateTimeAttribute::Container.parser
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param val Any adapter responding to #parse
|
16
|
+
def self.parser=(val)
|
17
|
+
DateTimeAttribute::Container.parser = val
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Symbol] attribute
|
21
|
+
# @return [Container]
|
22
|
+
def date_time_container(attribute)
|
23
|
+
(@date_time_container ||= {})[attribute] ||= DateTimeAttribute::Container.new(send(attribute))
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [String, Symbol, Proc, nil] zone Time zone
|
27
|
+
def in_time_zone(zone)
|
28
|
+
case zone
|
29
|
+
when nil
|
30
|
+
yield
|
31
|
+
when ActiveSupport::TimeZone, String
|
32
|
+
old_zone = Time.zone
|
33
|
+
Time.zone = zone
|
34
|
+
yield(zone).tap { Time.zone = old_zone }
|
35
|
+
when Proc, Symbol
|
36
|
+
old_zone = Time.zone
|
37
|
+
zone = instance_eval(&(zone.to_proc))
|
38
|
+
Time.zone = zone
|
39
|
+
yield(zone).tap { Time.zone = old_zone }
|
40
|
+
else
|
41
|
+
raise ArgumentError, "Expected timezone, got #{zone.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module ClassMethods
|
46
|
+
|
47
|
+
# @param [Symbol] attribute Attribute name
|
48
|
+
# @param [Hash<Symbol>] opts
|
49
|
+
# @option opts [String, Symbol, Proc, nil] :time_zone
|
50
|
+
def date_time_attribute(*attributes)
|
51
|
+
opts = attributes.extract_options!
|
52
|
+
time_zone = opts[:time_zone]
|
53
|
+
|
54
|
+
attributes.each do |attribute|
|
55
|
+
attribute = attribute.to_sym
|
56
|
+
|
57
|
+
# ActiveRecord issue: https://rails.lighthouseapp.com/projects/8994/tickets/4317-inconsistent-method_defined-bevahiour
|
58
|
+
if !(method_defined?(attribute) || (respond_to?(:attribute_method?) && attribute_method?(attribute)))
|
59
|
+
attr_accessor attribute
|
60
|
+
end
|
61
|
+
|
62
|
+
define_method("#{attribute}_date") do
|
63
|
+
in_time_zone(time_zone) do |time_zone|
|
64
|
+
date_time_container(attribute).in_time_zone(time_zone).date
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
define_method("#{attribute}_time") do
|
69
|
+
in_time_zone(time_zone) do |time_zone|
|
70
|
+
date_time_container(attribute).in_time_zone(time_zone).time
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
define_method("#{attribute}_time_zone") do
|
75
|
+
in_time_zone(time_zone) do |time_zone|
|
76
|
+
date_time_container(attribute).in_time_zone(time_zone).time_zone
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
define_method("#{attribute}_date=") do |val|
|
81
|
+
in_time_zone(time_zone) do |time_zone|
|
82
|
+
container = date_time_container(attribute).in_time_zone(time_zone)
|
83
|
+
(container.date = val).tap do
|
84
|
+
self.send("#{attribute}=", container.date_time)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
define_method("#{attribute}_time=") do |val|
|
90
|
+
in_time_zone(time_zone) do |time_zone|
|
91
|
+
container = date_time_container(attribute).in_time_zone(time_zone)
|
92
|
+
(container.time = val).tap do
|
93
|
+
self.send("#{attribute}=", container.date_time)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
define_method("#{attribute}_time_zone=") do |val|
|
99
|
+
in_time_zone(val) do |time_zone|
|
100
|
+
container = date_time_container(attribute).in_time_zone(time_zone)
|
101
|
+
self.send("#{attribute}=", container.date_time)
|
102
|
+
container.time_zone
|
103
|
+
end if val
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'active_support/core_ext/object/try'
|
2
|
+
require 'active_support/core_ext/time/zones'
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
|
5
|
+
module DateTimeAttribute
|
6
|
+
class Container < Struct.new(:date_time, :date, :time, :time_zone)
|
7
|
+
delegate :year, :month, :day, :hour, to: :date_time
|
8
|
+
|
9
|
+
# @param [String] time_zone
|
10
|
+
# @return [Container] self
|
11
|
+
def in_time_zone(time_zone)
|
12
|
+
self.time_zone = time_zone
|
13
|
+
update_date_time
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String, nil]
|
18
|
+
def time_zone
|
19
|
+
@time_zone
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [String] val
|
23
|
+
def time_zone=(val)
|
24
|
+
(@time_zone = val).tap { update_date_time }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [String, Date, Time, DateTime, nil] val
|
28
|
+
def date=(val)
|
29
|
+
@date = parse(val)
|
30
|
+
update_date_time
|
31
|
+
@date
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param [String, Date, Time, DateTime, nil] val
|
35
|
+
def time=(val)
|
36
|
+
@time = parse(val)
|
37
|
+
update_date_time
|
38
|
+
@time
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Date, String]
|
42
|
+
def date
|
43
|
+
@date || date_time
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Time, String]
|
47
|
+
def time
|
48
|
+
@time || date_time
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.parser
|
52
|
+
@parser || Time.zone || Time
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param val Parser used for parsing date/time string values
|
56
|
+
def self.parser=(val)
|
57
|
+
@parser = val
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def parse(val)
|
63
|
+
case val
|
64
|
+
when String
|
65
|
+
self.class.parser.parse(val)
|
66
|
+
when Date, Time, DateTime, ActiveSupport::TimeWithZone
|
67
|
+
val
|
68
|
+
when nil
|
69
|
+
else
|
70
|
+
raise ArgumentError, "Expected Date, Time, String, got #{val.class.name}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def update_date_time
|
75
|
+
if @date || @time
|
76
|
+
date_time = self.class.parser.parse("#{date.try(:strftime, '%Y-%m-%d')} #{time.try(:strftime, '%H:%M')}")
|
77
|
+
self.date_time = time_zone ? date_time.in_time_zone(time_zone) : date_time
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DateTimeAttribute::Container do
|
4
|
+
subject { described_class.new(Time.now) }
|
5
|
+
|
6
|
+
its(:year) { should == Time.now.year }
|
7
|
+
its(:month) { should == Time.now.month }
|
8
|
+
its(:day) { should == Time.now.day }
|
9
|
+
its(:hour) { should == Time.now.hour }
|
10
|
+
|
11
|
+
describe 'setters' do
|
12
|
+
before do
|
13
|
+
Time.zone = 'Pacific Time (US & Canada)'
|
14
|
+
end
|
15
|
+
|
16
|
+
subject(:target) { described_class.new(date_time, date, time) }
|
17
|
+
|
18
|
+
let(:date_time) { nil }
|
19
|
+
|
20
|
+
before do
|
21
|
+
target.date_time = date_time
|
22
|
+
target.date = date
|
23
|
+
target.time = time
|
24
|
+
end
|
25
|
+
|
26
|
+
context "nothing set" do
|
27
|
+
let(:date_time) { nil }
|
28
|
+
let(:date) { nil }
|
29
|
+
let(:time) { nil }
|
30
|
+
|
31
|
+
its(:date_time) { should be_nil }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "time set" do
|
35
|
+
let(:date) { nil }
|
36
|
+
let(:time) { '23:00' }
|
37
|
+
|
38
|
+
its(:year) { should == Time.zone.now.year }
|
39
|
+
its(:month) { should == Time.zone.now.month }
|
40
|
+
its(:day) { should == Time.zone.now.day }
|
41
|
+
its(:hour) { should == 23 }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "date set" do
|
45
|
+
let(:date) { '2001-02-03' }
|
46
|
+
let(:time) { nil }
|
47
|
+
|
48
|
+
its(:year) { should == 2001 }
|
49
|
+
its(:month) { should == 2 }
|
50
|
+
its(:day) { should == 3 }
|
51
|
+
|
52
|
+
it 'does not use current timezone' do
|
53
|
+
subject.hour.should == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
context "time set" do
|
57
|
+
let(:date) { '2001-02-03' }
|
58
|
+
let(:time) { '10:00pm' }
|
59
|
+
|
60
|
+
its(:year) { should == 2001 }
|
61
|
+
its(:month) { should == 2 }
|
62
|
+
its(:day) { should == 3 }
|
63
|
+
its(:hour) { should == 22 }
|
64
|
+
|
65
|
+
context "non string values" do
|
66
|
+
let(:date) { Date.new(2001, 02, 03) }
|
67
|
+
let(:time) { Time.new(2001, 02, 03, 04, 05) }
|
68
|
+
|
69
|
+
its(:year) { should == 2001 }
|
70
|
+
its(:month) { should == 2 }
|
71
|
+
its(:day) { should == 3 }
|
72
|
+
its(:hour) { should == 4 }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "time zone set" do
|
76
|
+
its(:year) { should == 2001 }
|
77
|
+
its(:month) { should == 2 }
|
78
|
+
|
79
|
+
specify do
|
80
|
+
expect { subject.time_zone = 'Moscow' }.to change { subject.time_zone }.from(nil).to('Moscow')
|
81
|
+
end
|
82
|
+
|
83
|
+
specify do
|
84
|
+
expect { subject.time_zone = 'Moscow' }.to change { subject.day }.from(3).to(4)
|
85
|
+
end
|
86
|
+
|
87
|
+
specify do
|
88
|
+
expect { subject.time_zone = 'Moscow' }.to change { subject.hour }.from(22).to(9)
|
89
|
+
end
|
90
|
+
|
91
|
+
context "different environment timezone set" do
|
92
|
+
before do
|
93
|
+
Time.zone = 'Krasnoyarsk'
|
94
|
+
end
|
95
|
+
|
96
|
+
its(:year) { should == 2001 }
|
97
|
+
its(:month) { should == 2 }
|
98
|
+
its(:day) { should == 3 }
|
99
|
+
its(:hour) { should == 22 }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DateTimeAttribute do
|
4
|
+
before do
|
5
|
+
Time.zone = 'Pacific Time (US & Canada)'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".parser" do
|
9
|
+
its(:parser) { should == Time.zone }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.date_time_attribute' do
|
13
|
+
let(:dummy_class) do
|
14
|
+
Class.new do
|
15
|
+
include DateTimeAttribute
|
16
|
+
date_time_attribute :due_at, :created_at
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
subject(:target) { dummy_class.new }
|
21
|
+
|
22
|
+
it { should respond_to :due_at }
|
23
|
+
it { should respond_to :due_at_time }
|
24
|
+
it { should respond_to :due_at_date }
|
25
|
+
it { should respond_to :created_at }
|
26
|
+
it { should respond_to :created_at_time }
|
27
|
+
it { should respond_to :created_at_date }
|
28
|
+
|
29
|
+
describe "values" do
|
30
|
+
let(:due_at) { nil }
|
31
|
+
let(:date) { nil }
|
32
|
+
let(:time) { nil }
|
33
|
+
let(:time_zone) { nil }
|
34
|
+
subject(:date_time) { target.due_at }
|
35
|
+
|
36
|
+
before do
|
37
|
+
target.due_at = due_at
|
38
|
+
target.due_at_date = date
|
39
|
+
target.due_at_time = time
|
40
|
+
target.due_at_time_zone = time_zone
|
41
|
+
end
|
42
|
+
|
43
|
+
context "nothing set" do
|
44
|
+
let(:due_at) { nil }
|
45
|
+
let(:date) { nil }
|
46
|
+
let(:time) { nil }
|
47
|
+
|
48
|
+
it { should be_nil }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "date_time set" do
|
52
|
+
let(:due_at) { Time.zone.now }
|
53
|
+
it { should_not be_nil }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "time set" do
|
57
|
+
let(:date) { nil }
|
58
|
+
let(:time) { '23:00' }
|
59
|
+
|
60
|
+
its(:year) { should == Time.zone.now.year }
|
61
|
+
its(:month) { should == Time.zone.now.month }
|
62
|
+
its(:day) { should == Time.zone.now.day }
|
63
|
+
its(:hour) { should == 23 }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "date set" do
|
67
|
+
let(:date) { '2001-02-03' }
|
68
|
+
let(:time) { nil }
|
69
|
+
|
70
|
+
its(:year) { should == 2001 }
|
71
|
+
its(:month) { should == 2 }
|
72
|
+
its(:day) { should == 3 }
|
73
|
+
its(:hour) { should == 0 }
|
74
|
+
|
75
|
+
context "time set" do
|
76
|
+
let(:date) { '2001-02-03' }
|
77
|
+
let(:time) { '10:00pm' }
|
78
|
+
|
79
|
+
its(:year) { should == 2001 }
|
80
|
+
its(:month) { should == 2 }
|
81
|
+
its(:day) { should == 3 }
|
82
|
+
its(:hour) { should == 22 }
|
83
|
+
|
84
|
+
context "timezone set explicitly" do
|
85
|
+
let(:time_zone) { 'Krasnoyarsk' }
|
86
|
+
|
87
|
+
its(:year) { should == 2001 }
|
88
|
+
its(:month) { should == 2 }
|
89
|
+
its(:day) { should == 3 }
|
90
|
+
its(:hour) { should == 22 }
|
91
|
+
|
92
|
+
specify do
|
93
|
+
subject.time_zone.name.should == 'Krasnoyarsk'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "time zone set on attribute" do
|
98
|
+
let(:dummy_class) do
|
99
|
+
Class.new do
|
100
|
+
include DateTimeAttribute
|
101
|
+
date_time_attribute :due_at, time_zone: 'Moscow'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
its(:year) { should == 2001 }
|
106
|
+
its(:month) { should == 2 }
|
107
|
+
its(:day) { should == 3 }
|
108
|
+
its(:hour) { should == 22 }
|
109
|
+
|
110
|
+
specify do
|
111
|
+
subject.time_zone.name.should == 'Moscow'
|
112
|
+
end
|
113
|
+
|
114
|
+
context "timezone set explicitly" do
|
115
|
+
let(:time_zone) { 'Krasnoyarsk' }
|
116
|
+
|
117
|
+
its(:year) { should == 2001 }
|
118
|
+
its(:month) { should == 2 }
|
119
|
+
its(:day) { should == 3 }
|
120
|
+
its(:hour) { should == 22 }
|
121
|
+
|
122
|
+
specify do
|
123
|
+
subject.time_zone.name.should == 'Krasnoyarsk'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "different timezone set" do
|
128
|
+
before do
|
129
|
+
Time.zone = 'Krasnoyarsk'
|
130
|
+
end
|
131
|
+
|
132
|
+
its(:year) { should == 2001 }
|
133
|
+
its(:month) { should == 2 }
|
134
|
+
its(:day) { should == 3 }
|
135
|
+
its(:hour) { should == 22 }
|
136
|
+
|
137
|
+
specify do
|
138
|
+
subject.time_zone.name.should == 'Moscow'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "timezone proc given" do
|
143
|
+
let(:dummy_class) do
|
144
|
+
Class.new do
|
145
|
+
include DateTimeAttribute
|
146
|
+
date_time_attribute :due_at, time_zone: Proc.new { 'Moscow' }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
its(:year) { should == 2001 }
|
151
|
+
its(:month) { should == 2 }
|
152
|
+
its(:day) { should == 3 }
|
153
|
+
its(:hour) { should == 22 }
|
154
|
+
|
155
|
+
specify do
|
156
|
+
subject.time_zone.name.should == 'Moscow'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "timezone method given" do
|
161
|
+
let(:dummy_class) do
|
162
|
+
Class.new do
|
163
|
+
include DateTimeAttribute
|
164
|
+
date_time_attribute :due_at, time_zone: :tz
|
165
|
+
|
166
|
+
def tz
|
167
|
+
'Moscow'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
its(:year) { should == 2001 }
|
173
|
+
its(:month) { should == 2 }
|
174
|
+
its(:day) { should == 3 }
|
175
|
+
its(:hour) { should == 22 }
|
176
|
+
|
177
|
+
specify do
|
178
|
+
subject.time_zone.name.should == 'Moscow'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "nil timezone" do
|
183
|
+
let(:dummy_class) do
|
184
|
+
Class.new do
|
185
|
+
include DateTimeAttribute
|
186
|
+
date_time_attribute :due_at, time_zone: :tz
|
187
|
+
|
188
|
+
def tz
|
189
|
+
nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it { should be_a(Time) }
|
195
|
+
its(:year) { should == 2001 }
|
196
|
+
its(:month) { should == 2 }
|
197
|
+
its(:day) { should == 3 }
|
198
|
+
its(:hour) { should == 22 }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: date_time_attribute
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergei Zinin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Allows to assign date and time attributes separately for a DateTime attribute
|
42
|
+
in your model instance. Plays with time zones as well.
|
43
|
+
email: szinin@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files:
|
47
|
+
- README.md
|
48
|
+
files:
|
49
|
+
- .coveralls.yml
|
50
|
+
- .gitignore
|
51
|
+
- .travis.yml
|
52
|
+
- Gemfile
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- date_time_attribute.gemspec
|
56
|
+
- lib/date_time_attribute.rb
|
57
|
+
- lib/date_time_attribute/container.rb
|
58
|
+
- spec/date_time_attribute/container_spec.rb
|
59
|
+
- spec/date_time_attribute_spec.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
homepage: http://github.com/einzige/date_time_attribute
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.1.5
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Splits DateTime attribute access into three separate Data, Time and TimeZone
|
85
|
+
attributes
|
86
|
+
test_files: []
|