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