47

Debian で Rails 3.2 と Ruby 1.9.3 を使用しています。HTML フォームを介して文字列の形式で日付、時刻、およびタイムゾーンを収集するアプリがあります。このようなもの:

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

私がしたいのは、これらの 3 つの要素を単一の日付に解析し、UTC としてデータベースに保存することです。この場合、UTC タイム ゾーンに入ると、開始時刻に 7 時間が追加されます。したがって、受信した中央時間ではなく、UTC として DB に保存されると、保存された時間は 17:00 になります。

日付を解析するために、次のようなことを試しました。

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

ただし、%Z を使用して結果の時間にタイム ゾーンを組み込むことはできません。解析しないか、時刻が中部時間ではなく UTC として解釈されます。だから私の質問は、保存されている実際の日付/時刻の値を変更せずに、日付文字列を特定のタイムゾーンに強制する方法です。将来のタイムゾーン変換が正確になるように、文字列をその時点で正しいタイムゾーンを含む日付/時刻オブジェクトに解析できるようにしたいと考えています。私はすべてを見てきましたが、これを行う方法が見つかりません。これは、HTML フォームから入力された日付に対して一般的に行われているように見えるため、奇妙です。助けてくれてありがとう。

4

7 に答える 7

56

使用String#in_time_zone(Rails 4+)

私は個人的に使用することを好み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

これにより、文字列の日付と時刻が指定されたタイム ゾーンに解析されます。

于 2015-08-10T19:56:47.123 に答える
24

%Zタイムゾーン名を指定する正しい方法です。次のことを試しましたか?

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)
于 2012-04-10T16:20:01.093 に答える
2

これが私が思いついた方法です。最もきれいではありませんが、機能します。指定された形式を使用して文字列を解析し、Time.zone.parse必要な形式に変換できます。

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

次に、別の質問で言及されているようなことを行うことができますが、指定された形式を使用します。

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

または、すでにタイムゾーンが設定されている場合:

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

%m/%d/%Yほとんどの場合、これがユーザー入力であるため、デフォルトの形式を使用しました。必要に応じてこれをカスタマイズするか、またはDateTimeiso8601 であると信じられているデフォルトの形式を使用することができます ( %FT%T%z)

于 2016-03-22T01:14:36.687 に答える
1

私はついにこれを行うための汚い、しかし決定的な方法を見つけました。

まず、プレーンな Ruby Time.strptime を次のように使用して文字列を解析します。

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

このようにして、解析された時刻を取得しますが、まだ正しいタイムゾーンではありません。これを修正するには、時刻を文字列形式に変換し、標準の ActiveSupport::TimeZone#parse で解析しましょう

Time.zone.parse(time.to_s)

結果は、時刻が正しいタイムゾーンに解析された ActiveSupport::TimeWithZone です。

このようにしなければならない理由は、ActiveSupport::TimeZone も ActiveSupport::TimeWithZone も strptime メソッドをサポートしていないからです。そのため、タイムゾーン情報を持たないコア Ruby strptime で Time を解析し、ActiveSupport オブジェクトで受け入れられる形式に変換してから、もう一度解析する必要があります。

于 2016-05-09T11:42:05.470 に答える
-1

DateTime に日付文字列を取得させ、日付文字列の値を変更せずに UTC 以外のタイムゾーンをアタッチするには、これを使用します。これは簡単で、うるう日でも壊れません :)

xx = DateTime.strptime("9/1/15 #{object.time_zone}", "%m/%d/%Y %Z")
于 2015-11-13T22:33:38.917 に答える