teasy 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +121 -2
- data/lib/teasy/version.rb +1 -1
- data/lib/teasy.rb +2 -1
- data/test/teasy/teasy_test.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9237135fe6b6ebdbbfda965105575687619541dd
|
4
|
+
data.tar.gz: 743861f57815c7d9e71cbd2430068babeb91869c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f991d7d9055565b603ee4fdac3ee055e2350a85335d5222ed759d973d4a1f0b0e350d7e8e567c6bfc3a2de037db8b47b7c57930d9b4936157c97b79612551f5
|
7
|
+
data.tar.gz: 97a5e37bd8be859daa782683f278157448cddca72f76385a762bd38f456534e25b860c1771cc31d91cb67c859bacf865b650601040bc9c72736a5dcc96395236
|
data/README.md
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
# Teasy
|
2
2
|
|
3
|
-
|
3
|
+
Handling time zones in Ruby made easy.
|
4
|
+
|
5
|
+
## Why should anyone use this?
|
6
|
+
|
7
|
+
It is astonishingly [difficult to work with time zones in general](https://www.youtube.com/watch?v=-5wpm-gesOY) and with time zones in Ruby in particular. The only two time zones you can get from native Ruby are UTC and your local time zone. Apart from that you may set offsets, but that is not the same as setting a time zone.
|
8
|
+
This has prompted frameworks like Rails to develop classes like `ActiveSupport::TimeWithZone`. Since there is need for more than two time zones in web development.
|
9
|
+
|
10
|
+
When looking for ways to work with time zones in Ruby you will find that the general advice is either to just use ActiveSupport's TimeWithZone or to use the TZInfo gem. The former has two troubles, first you get more than you wanted. Even when you only require the minimal amount of ActiveSupport classes needed to get TimeWithZone running - which isn't a fun thing to figure out - you will also load monkey patches to core Ruby classes into your code. Second it has some serious quirks that can get you, like this goodie:
|
11
|
+
```ruby
|
12
|
+
t = DateTime.new(2014).in_time_zone('Europe/Berlin')
|
13
|
+
t.equal? t # -> true
|
14
|
+
t.eql? t # -> false ... WTF?
|
15
|
+
t == t # -> true
|
16
|
+
```
|
17
|
+
That was reported [here](https://github.com/rails/rails/issues/14178) a few years ago. Overall the interface of TimeWithZone is very nice though and this gem took strong inspiration from it. However I dislike monkey patching and decided not to include convenience methods like `in_time_zone` for `Time` objects.
|
18
|
+
|
19
|
+
[TZInfo](https://github.com/tzinfo/tzinfo) is a great gem that provides accurate time zone information and methods to determine the period for a point in time. However the interface it provides to convert time objects is minimal and rather difficult to use. Thus this gem uses TZInfo as a source for time zone information and tries to provide a nice interface for working with time with zones. (By the way, ActiveSupports' TimeWithZone is based on TZInfo too.)
|
20
|
+
|
21
|
+
This gem also comes with a FloatingTime class, which is time without a zone. I.e., 5 a.m. in New York is the same as 5 a.m. in Berlin with regards to floating time. This is useful for events that should occur at a certain time irrespective of time zone. E.g., your wake up call at 8 a.m. which you wouldn't want to ring at 2 in the morning just because you switched time zones.
|
22
|
+
|
23
|
+
## Why you should use this tentatively
|
24
|
+
|
25
|
+
It's tested and I spend much thought on it. But I'm not perfect and there's bound to be bugs. I'll start using this gem productively which will give me some feedback. But right now I have only what my tests tell me.
|
26
|
+
I'm sure there is room for improvement and there will be refactorings. However for now I need to use it and I'd be happy if you did too! So that I can get some feedback and see what needs to change.
|
4
27
|
|
5
28
|
## Installation
|
6
29
|
|
@@ -20,7 +43,103 @@ Or install it yourself as:
|
|
20
43
|
|
21
44
|
## Usage
|
22
45
|
|
23
|
-
|
46
|
+
### TimeWithZone
|
47
|
+
#### Create a TimeWithZone object
|
48
|
+
```ruby
|
49
|
+
# Simply call the constructor
|
50
|
+
Teasy::TimeWithZone.new(2042, 4, 2, 0, 30, 45, 1.112, 'Europe/Berlin') # -> 2042-04-02 00:30:45 +0200
|
51
|
+
|
52
|
+
# leaving out the time zone will result in the default time zone being used, which by default is UTC
|
53
|
+
Teasy::TimeWithZone.new(2042, 4, 2, 0, 30, 45, 1.112) # -> 2042-04-02 00:30:45 UTC
|
54
|
+
|
55
|
+
# that default time zone can be set though
|
56
|
+
Teasy.default_zone = 'America/New_York' # -> "America/New_York"
|
57
|
+
Teasy::TimeWithZone.new(2042, 4, 2, 0, 30, 45, 1.112) # -> 2042-04-02 00:30:45 -0400
|
58
|
+
|
59
|
+
# you can also use the block syntax to temporarily change the default time zone
|
60
|
+
Teasy.with_zone('Europe/Berlin') do
|
61
|
+
Teasy::TimeWithZone.new(2042, 4, 2, 0, 30, 45, 1.112) # -> 2042-04-02 00:30:45 +0200
|
62
|
+
end
|
63
|
+
|
64
|
+
# You can also initialize a Teasy::TimeWithZone object from time objects
|
65
|
+
Teasy::TimeWithZone.from_time(Time.utc(2042), 'Europe/Berlin') # -> 2042-01-01 00:00:00 +0100
|
66
|
+
Teasy::TimeWithZone.from_time(Time.utc(2042), 'America/New_York') # -> 2042-01-01 00:00:00 -0500
|
67
|
+
|
68
|
+
# this method interpretes the time object to be in the time zone specified,
|
69
|
+
# if you want it to convert to another time zone use #from_utc instead
|
70
|
+
# where it is assumed that the time object is in UTC time.
|
71
|
+
Teasy::TimeWithZone.from_utc(Time.utc(2042), 'Europe/Berlin') # -> 2042-01-01 01:00:00 +0100
|
72
|
+
Teasy::TimeWithZone.from_utc(Time.utc(2042), 'America/New_York') # -> 2041-12-31 19:00:00 -0500
|
73
|
+
```
|
74
|
+
|
75
|
+
#### Convert between time zones
|
76
|
+
```ruby
|
77
|
+
# convert a Teasy::TimeWithZone object in place to another time zone by calling #in_time_zone!
|
78
|
+
time_with_zone # -> 2042-01-01 01:00:00 +0100
|
79
|
+
time_with_zone.in_time_zone!('America/New_York') # -> 2041-12-31 19:00:00 -0500
|
80
|
+
time_with_zone # -> 2041-12-31 19:00:00 -0500
|
81
|
+
|
82
|
+
# convert it without changing the original object by calling #in_time_zone
|
83
|
+
time_with_zone # -> 2042-01-01 01:00:00 +0100
|
84
|
+
time_with_zone.in_time_zone('Asia/Calcutta') # -> 2042-01-01 05:30:00 +0530
|
85
|
+
time_with_zone # -> 2042-01-01 01:00:00 +0100
|
86
|
+
```
|
87
|
+
|
88
|
+
#### Comparisons
|
89
|
+
As long as a `TimeWithZone` converts to the same utc time it is `==` and `eql?` to another `TimeWithZone`.
|
90
|
+
If the other is not a `TimeWithZone`, then only `==` will return true (since it performs a conversion), given that other responds to `to_time`. `eql?` will not perform a conversion - similiar to how `Numeric` works in Ruby.
|
91
|
+
|
92
|
+
Examples:
|
93
|
+
```ruby
|
94
|
+
calcutta_time = Teasy::TimeWithZone.from_utc(Time.utc(2042), 'Asia/Calcutta') # -> 2042-01-01 05:30:00 +0530
|
95
|
+
ny_time = Teasy::TimeWithZone.from_utc(Time.utc(2042), 'America/New_York') # -> 2041-12-31 19:00:00 -0500
|
96
|
+
|
97
|
+
ny_time == calcutta_time # -> true
|
98
|
+
ny_time.eql? calcutta_time # -> true
|
99
|
+
|
100
|
+
calcutta_time == Time.utc(2042) # -> true
|
101
|
+
calcutta_time.eql? Time.utc(2042) # -> false
|
102
|
+
```
|
103
|
+
|
104
|
+
### FloatingTime
|
105
|
+
#### Create a FloatingTime object
|
106
|
+
```ruby
|
107
|
+
# Simply call the constructor
|
108
|
+
Teasy::FloatingTime.new(2042, 4, 2, 0, 30, 45, 1.112) # -> 2042-04-02 00:30:45
|
109
|
+
|
110
|
+
# or create one from a time object
|
111
|
+
Teasy::FloatingTime.from_time(Time.utc(2042)) # -> 2042-01-01 00:00:00
|
112
|
+
|
113
|
+
# the zone doesn't matter
|
114
|
+
Teasy::FloatingTime.from_time(Time.local(2042)) # -> 2042-01-01 00:00:00
|
115
|
+
|
116
|
+
# also, it doesn't have to be a time object, as long as it responds to
|
117
|
+
# :year, :mon, :day, :hour, :min, :sec and :nsec
|
118
|
+
time_with_zone = Teasy::TimeWithZone.from_time(Time.utc(2042), 'Asia/Calcutta') # -> 2042-01-01 00:00:00 +0530
|
119
|
+
Teasy::FloatingTime.from_time(time_with_zone) # -> 2042-01-01 00:00:00
|
120
|
+
```
|
121
|
+
|
122
|
+
#### Comparisons
|
123
|
+
When the year, month, day, hour, minute, second and nano-second of two `FloatingTime` objects are the same then `eql?` and `==` return true. When the other object is not a FloatingTime but responds to `to_time` and `utc_offset` then `==` will return true if the aforementioned list of attributes are equal. However, `eql?` again does not perform any conversion and thus will return false for any object that is not a `FloatingTime`.
|
124
|
+
|
125
|
+
Examples:
|
126
|
+
```ruby
|
127
|
+
floating_time = Teasy::FloatingTime.from_time(Time.utc(2042)) # -> 2042-01-01 00:00:00
|
128
|
+
other_floating_time = Teasy::FloatingTime.from_time(Time.utc(2042, 1, 1, 1)) # -> 2042-01-01 01:00:00
|
129
|
+
ny_time = Teasy::TimeWithZone.from_time(Time.utc(2042), 'America/New_York') # -> 2042-01-01 00:00:00 -0500
|
130
|
+
other_ny_time = Teasy::TimeWithZone.from_utc(Time.utc(2042), 'America/New_York') # -> 2041-12-31 19:00:00 -0500
|
131
|
+
|
132
|
+
floating_time == other_floating_time # -> false
|
133
|
+
floating_time.eql? other_floating_time # -> false
|
134
|
+
|
135
|
+
floating_time == floating_time.dup # -> true
|
136
|
+
floating_time.eql? floating_time.dup # -> true
|
137
|
+
|
138
|
+
floating_time == Time.utc(2042) # -> true
|
139
|
+
floating_time == ny_time # -> true
|
140
|
+
floating_time == other_ny_time # -> false
|
141
|
+
[Time.utc(2042), ny_time, other_ny_time].any? { |time| floating_time.eql? time } # -> false
|
142
|
+
```
|
24
143
|
|
25
144
|
## Contributing
|
26
145
|
|
data/lib/teasy/version.rb
CHANGED
data/lib/teasy.rb
CHANGED
data/test/teasy/teasy_test.rb
CHANGED