Rails: How to parse date-time string into a specific time zone

巧了我就是萌 提交于 2019-12-17 10:53:09

问题


I'm using Rails 3.2 and ruby 1.9.3 on Debian. I have an app that collects a date, time, and timezone in the form of strings via an HTML form. Something like this:

start_date: "04-15-2010",
start_time: "10:00:00",
timezone: "Central Time (US & Canada)"

What I'd like to do is parse these 3 elements into a single date that is saved into my database as UTC, which in this case would add 7 hours to the start time, once it's in the UTC time zone. So the stored time would be 17:00 once it's in the DB as UTC instead of the received Central time.

I have tried something like this to parse the date:

ActiveSupport::TimeZone[timezone].at DateTime.strptime("{ 2012-04-09 20:00:00 }", "{ %Y-%m-%d %H:%M:%S }").to_i

However, I'm not able to incorporate the time zone into the resulting time with %Z. It either doesn't parse or the time is interpreted as UTC not Central time. So my question is, how to coerce a date string into a certain time zone without changing the value of the actual date/time stored. I'd like to be able to parse the string into a date/time object that includes the correct time zone with it at that time so that future time zone conversions are accurate. I've looked all over and can't find a way to do this. It's strange, since this seems like something common one does with dates inputted from HTML forms. Thank you for any help.


回答1:


%Z is the correct way to specify a Time zone name. Have you tried the following ?

date_and_time = '%m-%d-%Y %H:%M:%S %Z'
DateTime.strptime("04-15-2010 10:00:00 Central Time (US & Canada)",date_and_time)



回答2:


Try this:

zone = "Central Time (US & Canada)"  

ActiveSupport::TimeZone[zone].parse("2013-04-03 17:47:00")



回答3:


Use String#in_time_zone (Rails 4+)

I personally prefer using String#in_time_zone:

>> '22.09.1986 10:30'.in_time_zone('Central Time (US & Canada)')
# => Mon, 22 Sep 1986 10:30:00 CDT -05:00

This parses the date and time in the String into the time zone provided.




回答4:


This is the method that I came up with. Not the prettiest, but it works. Allows parsing the string using a specified format, and then turning it into the format that I know Time.zone.parse requires.

class ActiveSupport::TimeZone
  def strptime(time, format='%m/%d/%Y')
    formatted = Time.strptime(time, format).strftime('%Y-%m-%d %T')
    parse(formatted)
  end
end

Then you can do something like what was mentioned in another question, but with a specified format:

zone = "Central Time (US & Canada)"  
ActiveSupport::TimeZone[zone].strptime('2013-04-03', '%Y-%m-%d')

Or if you already have a time zone set:

Time.zone = "Central Time (US & Canada)" 
Time.zone.strptime('01/13/2006')

I used a default format of %m/%d/%Y because that's what my user input is most of the time. You can customize this to your needs, or use the default format DateTime uses which is believe is iso8601 (%FT%T%z)




回答5:


I've finally found the dirty, yet definitive way to do this.

First, parse the string using plain Ruby Time.strptime like this:

time = Time.strptime('12 : 00 : PM', '%I : %M : %p')

This way you get the parsed Time, but not yet in correct timezone. To fix that, let's convert the time to string form and parse it with the standard ActiveSupport::TimeZone#parse

Time.zone.parse(time.to_s)

The result is the ActiveSupport::TimeWithZone with our time parsed into the correct timezone.

The reason why we have to do it this way is that neither ActiveSupport::TimeZone nor ActiveSupport::TimeWithZone support the strptime method. So we have to parse the Time with core Ruby strptime that does not have timezone information, convert it to format acceptable in ActiveSupport objects and then parse it yet again.




回答6:


To have DateTime take the date string and attach a timezone other than UTC without changing the values of the date string , use this, its easy , doesnt break on leap day :)

xx = DateTime.strptime("9/1/15 #{object.time_zone}", "%m/%d/%Y %Z")



回答7:


Convert specific date format in UTC.

ActiveSupport::TimeZone['UTC'].parse(Time.strptime('01/24/2019T16:10:16', "%m/%d/%YT%H:%M:%S").asctime)


来源:https://stackoverflow.com/questions/10091959/rails-how-to-parse-date-time-string-into-a-specific-time-zone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!