1

I'm creating an application that requires dates & times to be stored. Currently, I'm creating a time like this:

Time.strptime("2013-12-08 04:15pm PST", "%Y-%m-%d %H:%M%P %Z")
=> 2013-12-09 00:15:00 +0000

I'm cool with storing this in the database, but my question is about daylight savings time. When I do this:

Time.strptime("2013-06-08 04:15pm PST", "%Y-%m-%d %H:%M%P %Z")
=> 2013-06-09 00:15:00 +0000

It doesn't seem to have adjusted itself for daylight savings. Am I wrong in thinking this? How can I know that when I create a object with a time attribute that I'll be able to retrieve that exact time in the future?

How can I best read the string date from a user, save it in utc in the database, and retrieve it later to display exactly without worrying about DST?

I know a lot of answers say to use the config.time_zone in rails, but my application will eventually be cross-timezone.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
mr_mariusz
  • 644
  • 7
  • 12
  • I'm not sure what you are trying to achieve, but lets suppose `user1` posts something in a timezone and `user2` read it in another timezone. You can save the time with `user1` timezone just normalize it to +0. Either way, you will need to manually adjust the time zone according to `user2` configurations to display to him. I'm not sure if there is a better way to deal with time zones automatically. – fotanus Oct 07 '13 at 19:50

3 Answers3

2

PST is Pacific Standard Time. If you want daylight savings time, the string is PDT. I think if you convert PST to PDT, it will do what you want.

# this is summer (PDT)
Time.strptime("2013-06-08 04:15pm PDT", "%Y-%m-%d %H:%M%P %Z") 

# this is winter (PST)
Time.strptime("2013-12-08 04:15pm PST", "%Y-%m-%d %H:%M%P %Z")
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • `Time.strptime("2013-06-08 04:15pm PDT", "%Y-%m-%d %H:%M%P %Z")` => 2013-06-08 23:15:00 +0000 `Time.strptime("2013-12-08 04:15pm PDT", "%Y-%m-%d %H:%M%P %Z")` => 2013-12-08 23:15:00 +0000 – mr_mariusz Oct 07 '13 at 19:54
  • 1
    I'm not sure what country you are from, but typically summer time in Silicon Valley is PDT and winter time is PST. Try `Time.strptime("2013-06-08 04:15pm PDT", "%Y-%m-%d %H:%M%P %Z")` and `Time.strptime("2013-12-08 04:15pm PST", "%Y-%m-%d %H:%M%P %Z")` – Mark Lakata Oct 07 '13 at 19:56
  • I see how it works now, I didn't understand before. However, I am looking for a way to figure out the PDT/PST part because I'm only getting "2013-12-08 04:15pm" from the user and know where their address is. So, from the address I can get the "Pacific Time (US & Canada)" part. Next, I'll need to find out whether its DST for the date they provided. This is what blows my mind because I feel like there should be a method that does this for me. – mr_mariusz Oct 07 '13 at 20:13
  • @user1493849 - Have you tried leaving out the %Z and the "PST/PDT" part? It might just work. Assuming you are running on an OS that is smart enough to know all the details of timezones, it may just work. – Mark Lakata Oct 07 '13 at 23:05
1

Figured it out. Special thanks to @MarkLakata for pointing out the differences between PDT and PST. Turns out we can't rely on these to play with dates. In my app, I do know the geographic location of my Property though. For now, it's "Pacific Time (US & Canada)", but later I may have properties from many other locations. I want to schedule cleanings in the future. In the real world, people don't usually reschedule around DST. So if I say I'm doing something at 4:15pm, I mean it whether it's DST or not, and I need my app to behave the same way.

property.timezone
=> "Pacific Time (US & Canada)"

Time.zone = property.timezone 
=> "Pacific Time (US & Canada)"

time = Time.zone.parse("2013-12-08 04:15pm").utc
=> 2013-12-09 00:15:00 UTC

time = Time.zone.parse("2013-10-08 04:15pm").utc #DST
=> 2013-10-08 23:15:00 UTC

I store my cleaning_date attribute in a PostgreSQL DateTime field on Heroku. I know the timezone from the property, so I can save it after I parse it from the front end.

property.update(:cleaning_time => time)

To get it back from the database, I just do this:

def cleaning_date_string
  self.cleaning_time.in_time_zone("Pacific Time (US & Canada)").strftime("%m/%d/%Y")
end

def cleaning_time_string
  self.cleaning_time.in_time_zone("Pacific Time (US & Canada)").strftime("%l:%M%P")
end

Unfortunately, this is the only way I found to save a precise time in the database and retrieve it the exact same way. This seems to work locally and on Heroku.

addition:
This seems to be thread safe according to: Setting Time.zone during a request: Thread Safe?

Community
  • 1
  • 1
mr_mariusz
  • 644
  • 7
  • 12
  • You hit on an important point. You are scheduling *future* times, in which case UTC is not as important as the local time + time zone pair. See also [this answer](http://stackoverflow.com/a/19170823/634824) which touches on these points but was for a Java developer. – Matt Johnson-Pint Oct 08 '13 at 18:01
0

You should not rely on time zone abbreviations. They may be useful for humans, but they are horrible for computers. For example, "CST" might mean "Central Standard Time", and if you are in the USA you might know what that means. But it also might mean "China Standard Time" or "Cuba Standard Time". There is a reasonably good list of time zone abbreviations here, which clearly shows there are duplicates. Even this list isn't based on anything official.

Instead of "PST", you should instead use a time zone identifier, such as the IANA "America/Los_Angeles", or Rails "Pacific Time (US & Canada)".

You can use Rails's ActiveSupport::TimeZone which has some customized time zones, or if you prefer something more universally standard then you should use the TZInfo Ruby Gem, which takes IANA zone identifiers.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575