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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c029c09c43c7d2f53444146e45352eea16c00a0
4
- data.tar.gz: c18c15ff0af658d6f561121b2747e3e46258e95a
3
+ metadata.gz: 9237135fe6b6ebdbbfda965105575687619541dd
4
+ data.tar.gz: 743861f57815c7d9e71cbd2430068babeb91869c
5
5
  SHA512:
6
- metadata.gz: e3bb7266d199fcecf2c9a245c57a5fff334500f0e096d7e46adf81b8d8762b836ade69a5d5763007d3e8102af719fa5d9e7be47424aecb430ad238c014a8f956
7
- data.tar.gz: e207e2590e5636eb06e76f7949d777eaba7a6c36fc7a61567c0d500c0507c67bf48016e9c1e18d1e10e18edc7d7b24195720567a7f25de10a6b36b7220e51394
6
+ metadata.gz: 6f991d7d9055565b603ee4fdac3ee055e2350a85335d5222ed759d973d4a1f0b0e350d7e8e567c6bfc3a2de037db8b47b7c57930d9b4936157c97b79612551f5
7
+ data.tar.gz: 97a5e37bd8be859daa782683f278157448cddca72f76385a762bd38f456534e25b860c1771cc31d91cb67c859bacf865b650601040bc9c72736a5dcc96395236
data/README.md CHANGED
@@ -1,6 +1,29 @@
1
1
  # Teasy
2
2
 
3
- Timezone handling made easy.
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
- TODO: Write usage instructions here
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
@@ -1,3 +1,3 @@
1
1
  module Teasy
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/lib/teasy.rb CHANGED
@@ -14,7 +14,8 @@ module Teasy
14
14
  def self.with_zone(zone)
15
15
  old_zone = Thread.current[:teasy_default_zone]
16
16
  Thread.current[:teasy_default_zone] = zone
17
- yield
17
+ block_result = yield
18
18
  Thread.current[:teasy_default_zone] = old_zone
19
+ block_result
19
20
  end
20
21
  end
@@ -36,5 +36,6 @@ class TeasyTest < Minitest::Test
36
36
  assert_equal 'Europe/Berlin', Teasy.default_zone
37
37
  end
38
38
  assert_equal 'UTC', Teasy.default_zone
39
+ assert_equal 1, Teasy.with_zone('Europe/Berlin') { 1 }
39
40
  end
40
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teasy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kai Kuchenbecker