Skip to content

Instantly share code, notes, and snippets.

@stormzhang
Forked from wdiechmann/time_zone_io.md
Created November 13, 2012 14:23
Show Gist options
  • Save stormzhang/4065996 to your computer and use it in GitHub Desktop.
Save stormzhang/4065996 to your computer and use it in GitHub Desktop.
time and time again, your rails will come clean :)

Started out with what that frustrating issue that bites many a Rails developer (judging from just a tad over 24hrs googling and reading blogs etc) - time_zone! I'm on ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.4.2] - Rails 3.2.8 config.time_zone = 'Copenhagen'

and initially, I wanted to bark up this three, 'with the pack'

[31] pry(main)> ent.enter_at=Time.now 
=> 2012-11-13 11:52:45 +0100
[32] pry(main)> ent.save
   (0.1ms)  BEGIN
   (0.4ms)  UPDATE `entrances` SET `enter_at` = '2012-11-13 10:52:45', `updated_at` = '2012-11-13 10:52:55' WHERE `entrances`.`id` = 1
  SQL (0.2ms)  INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2012-11-13 10:52:55', 'update', 1, 'Entrance', '---\nox_id: 1\nemployee_id: 9\nwage_item_id: !!null \nenter_at: 2012-11-13 08:02:00.000000000Z\nleft_at: 2012-10-11 21:21:00.000000000Z\nreason: tyuio\nstate: drafted\nactive: true\ncreated_at: 2012-10-11 09:02:52.000000000Z\nupdated_at: 2012-11-13 06:39:07.000000000Z\nid: 1\n', NULL)
   (0.5ms)  COMMIT
=> true
[34] pry(main)> reload!
Reloading...
=> true
[35] pry(main)> Entrance.first
  Entrance Load (0.3ms)  SELECT `entrances`.* FROM `entrances` WHERE (entrances.ox_id='1') LIMIT 1
=> #<Entrance id: 1, ox_id: 1, employee_id: 9, wage_item_id: nil, enter_at: "2012-11-13 10:52:45", left_at: "2012-10-11 21:21:00", reason: "tyuio", state: "drafted", active: true, created_at: "2012-10-11 09:02:52", updated_at: "2012-11-13 10:52:55">
[37] pry(main)> Entrance.first.enter_at.to_s(:entrance)
  Entrance Load (0.4ms)  SELECT `entrances`.* FROM `entrances` WHERE (entrances.ox_id='1') LIMIT 1
=> "2012-11-13 11:52:45 +0100"

Everything is dandy ;)

[39] pry(main)> date=Date.today
=> Tue, 13 Nov 2012
[40] pry(main)> date=Date.today.to_datetime
=> Tue, 13 Nov 2012 00:00:00 +0000
[44] pry(main)> date += 1.hour + 30.minutes
=> Tue, 13 Nov 2012 01:30:00 +0000
[45] pry(main)> ent.enter_at
=> Tue, 13 Nov 2012 11:52:45 CET +01:00
[46] pry(main)> ent.enter_at = date
=> Tue, 13 Nov 2012 01:30:00 +0000
[47] pry(main)> ent.save
   (0.2ms)  BEGIN
   (0.6ms)  UPDATE `entrances` SET `enter_at` = '2012-11-13 01:30:00', `updated_at` = '2012-11-13 11:27:08' WHERE `entrances`.`id` = 1
  SQL (0.3ms)  INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2012-11-13 11:27:08', 'update', 1, 'Entrance', '---\nox_id: 1\nemployee_id: 9\nwage_item_id: !!null \nenter_at: 2012-11-13 10:52:45.000000000Z\nleft_at: 2012-10-11 21:21:00.000000000Z\nreason: tyuio\nstate: drafted\nactive: true\ncreated_at: 2012-10-11 09:02:52.000000000Z\nupdated_at: 2012-11-13 10:52:55.000000000Z\nid: 1\n', NULL)
   (0.6ms)  COMMIT
=> true
[48] pry(main)> reload!
Reloading...
=> true
[49] pry(main)> ent=Entrance.first
  Entrance Load (0.5ms)  SELECT `entrances`.* FROM `entrances` WHERE (entrances.ox_id='1') LIMIT 1
=> #<Entrance id: 1, ox_id: 1, employee_id: 9, wage_item_id: nil, enter_at: "2012-11-13 01:30:00", left_at: "2012-10-11 21:21:00", reason: "tyuio", state: "drafted", active: true, created_at: "2012-10-11 09:02:52", updated_at: "2012-11-13 11:27:08">
[50] pry(main)> ent.enter_at
=> Tue, 13 Nov 2012 02:30:00 CET +01:00
[51] pry(main)> date.class
=> DateTime
[52] pry(main)> ent.enter_at.class
=> ActiveSupport::TimeWithZone

Which is very much not dandy - but you see, then I took a very good look at date

[64] pry(main)> date.to_time
=> 2012-11-13 01:30:00 UTC
[65] pry(main)> date.in_time_zone
=> Tue, 13 Nov 2012 02:30:00 CET +01:00

and all at once I realized that the DB really was doing exactly what I was telling it to! It stored a point in time (in another time_zone) and was kind enough to show it correctly to me, once I asked for it.

Likewise - once I started storing the date/time correctly, everything was/is back to 'dandy'

[66] pry(main)> ent.enter_at = date.in_time_zone
=> Tue, 13 Nov 2012 02:30:00 CET +01:00
[67] pry(main)> ent.save
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
=> true
[68] pry(main)> ent.reload
  Entrance Load (0.3ms)  SELECT `entrances`.* FROM `entrances` WHERE `entrances`.`id` = 1 LIMIT 1
=> #<Entrance id: 1, ox_id: 1, employee_id: 9, wage_item_id: nil, enter_at: "2012-11-13 01:30:00", left_at: "2012-10-11 21:21:00", reason: "tyuio", state: "drafted", active: true, created_at: "2012-10-11 09:02:52", updated_at: "2012-11-13 11:27:08">
[69] pry(main)> ent.enter_at
=> Tue, 13 Nov 2012 02:30:00 CET +01:00
[70] pry(main)> 

But wait - wasn't it 1 1/2 hr I wanted to add to 'start_of_day'? Sure - my offset was just - well - off ;)

[70] pry(main)> date=Date.today.to_datetime.in_time_zone
=> Tue, 13 Nov 2012 01:00:00 CET +01:00
[71] pry(main)> date+=1.hour+30.minutes
=> Tue, 13 Nov 2012 02:30:00 CET +01:00

In my opinion Rails is doing the right thing - I just had to "get up to speed on how to use it" <:(

I hope somebody will find this post sooner than I did :)

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment