2016-05-20 3 views
0

CSVファイルからデータをインポートしていて、ユーザがDateTimeカラムのフォーマットを指定できるようにします。フォーマット文字列を入力して入力の妥当性を確認するという苦労を処理するのではなく、すべてのフォーマットオプション(例えば、%m/%d/%Yなど)をリストする選択ボックスを与える予定でした。誰かが、妥当なDateTime形式をすべて列挙する宝石がすでに存在していると述べましたが、それを見つけることができませんでした。表示するために使用可能なDateTime形式のリストを取得するにはどうすればよいですか?Ruby:リストのDateTimeフォーマットオプション

+0

ようこそ。 「Stack Overflowのための本やツール、ソフトウェアライブラリ、チュートリアル、その他のオフサイトリソースをお薦めするかどうかを尋ねる質問は、オピニオン回答とスパムを引き付ける傾向があるため、 //meta.stackoverflow.com/questions/254393)、それを解決するためにこれまでに何が行われているのか」 –

答えて

1

他にも興味があります。あまりにもずっと前と同じようなことをしなければならず、ほぼ任意の日付形式をサポートしていました。最後に、私たちがサポートしているすべてのデータソース(CSVファイル)から、29種類の異なるフォーマット(米国とカナダのすべての国)を検出しました。

私は結果を解析してキャッシュするために、このクラスを思い付いた:

class DateParser 
    @@date_cache = {} 

    def self.is_date?(date) 
    return self.match_digital_date?(date) || self.match_instance_date?(date) 
    end 

    def self.parse_date(date) 
    return nil if date.blank? 
    return date if date.instance_of?(Date) 

    date = date.to_s 
    cached_date = @@date_cache[date] 

    return cached_date if !cached_date.nil? 

    match = self.match_instance_date?(date) 

    if !match.nil? 
     month_str = match[1].upcase 
     day = match[2].to_i 
     year = match[3].to_i 
     year += (year < 20) ? 2000 : 1900 if year < 1600 

     month = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'].find_index {|mon| mon == month_str } 
     cached_date = Date.new(year, month+1, day) if !month.nil? 
    else 
     scrubbed_date = date.gsub(/^([0-9]+)[\/-]+([0-9]+)[\/-]+00$/, '\\1/\\2/2000') 
     begin 
     parsed = Chronic.parse(scrubbed_date) 
     rescue 
     parsed = nil 
     end 
     return nil if parsed.nil? 

     cached_date = parsed.to_date 
    end 

    @@date_cache[date] = cached_date 
    return cached_date 
    end 

private 

    # Matches dates in these formats 
    # : 2015-01-13 
    # : 01-13-2015 
    # : 01-13-15 
    # : 13-01-15 
    # : 01/13/2015 
    # : 01/13/15 
    # : 13/01/15 
    def self.match_digital_date?(date) 
    return /^([0-9]+)[\/-]+([0-9]+)[\/-]+([0-9]+)$/.match(date) 
    end 

    def self.match_instance_date?(date) 
    return /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d+)\/(\d+)/i.match(date) 
    end 
end 

これは、同様に、解析パスを選択するために、最初の正規表現の一致に基づいて、日付の解析の一部を行うためにChronic gemを使用しています私たちが途中で遭遇したいくつかの必要なフィックスアップとして。このアプローチの主な目的は、正確さとスピードでした。結果をキャッシュすると、ほとんどの場合、CSVファイルからの日付処理を5倍以上高速化できました。

あなたが使用したフォーマットをユーザーに尋ねずに、選択した日付を消費して取得したい場合は、必要なものを提供する必要があります。

1

DateTimeクラスをチェックしてください。これは標準的なライブラリの一部であり、外部の宝石ではありません。使用するにはrequire dateが必要です。

ここにirbの例があります。 strftimeには柔軟性があり、独自のフォーマット文字列を指定する必要があることに注意してください。

2.3.0 :007 > dt = DateTime.now 
=> #<DateTime: 2016-05-21T03:16:51+08:00 ((2457529j,69411s,139202000n),+28800s,2299161j)> 
2.3.0 :008 > dt.iso8601 
=> "2016-05-21T03:16:51+08:00" 
2.3.0 :009 > dt.xmlschema 
=> "2016-05-21T03:16:51+08:00" 
2.3.0 :010 > dt.jisx0301 
=> "H28.05.21T03:16:51+08:00" 
2.3.0 :011 > dt.rfc3339 
=> "2016-05-21T03:16:51+08:00" 
2.3.0 :012 > dt.httpdate 
=> "Fri, 20 May 2016 19:16:51 GMT" 
2.3.0 :013 > dt.strftime('%Y-%m-%dT%H:%M:%S%z') 
=> "2016-05-21T03:16:51+0800" 
関連する問題