2016-12-09 3 views
1

BESCHREIBUNGArbeiten mit Datum Zeit Zeichenfolge

I-Eingang als String Datum zu erhalten, muß die vollständige Datum Zeitformat mit Zeitzone sein kann, ist es nur mehr aktuell sein könnte, könnte es nur Zeit im 24-Stunden-Format , Zeit mit Zeitzone im 24-Stunden-Format oder eine Zeit in am und pm oder eine beliebige Kombination von oben.

Als Ausgabe möchte ich aktuelle (oder angegebene) Datum zusammen mit Zeit im 24-Stunden-Format und einer Zeitzone, die wir in einem Rubin Time.parse() analysieren können. Ich habe etwas gearbeitet, und Sie können den Quellcode unten finden. Ich habe auch rspec (Testfall) für einige der Erwartung hinzugefügt.

Sie können Ihre eigene Lösung bereitstellen oder meine Quelle aktualisieren, wie Sie möchten.

Beispiele

HINWEIS: hier ist zu erwarten Datum aktuelles Datum, wenn das Datum "2016-1-1T01:00:00 +0000" erhalten umgewandelt "2016-1-1T22:00:00 +0500" erhalten umgewandelt nicht

bereitgestellt
  1. '2200+5' sollte
  2. '100' sollte
  3. '1700+8' sollte "2016-1-1T17:00:00 +0800"
  4. '5pm+8' konvertiert werden sollten
  5. '5am+8'-"2016-1-1T17:00:00 +0800" konvertiert werden soll konvertiert werden zu "2016-1-1T5:00:00 +0800"
  6. '2016-12-15T2300+5' sollte
  7. '530pm+8'-"2016-1-1T17:30:00 +0000" erhalten umgewandelt
  8. '1730'-'2016-12-15T23:00:00 +0500' konvertiert werden sollten sollte konvertierte erhalten zu "2016-1-1T17:30:00 +0800"
  9. '1210am+8' sollte "2016-1-1T12:10:00 +0800" konvertiert werden

RSpec

describe "should convert datetime to accepted format" 
    Timecop.freeze(Time.utc(2016,1,1,2,0,0)) 
    it {expect(parse('2200+5')).to eq({time: Time.parse("2016-1-1T22:00:00 +0500")})} 
    it {expect(parse('100')).to eq({time: Time.parse("2016-1-1T01:00:00 +0000")})} 
    it {expect(parse('1700+8')).to eq({time: Time.parse("2016-1-1T17:00:00 +0800")})} 
    it {expect(parse('5pm+8')).to eq({time: Time.parse("2016-1-1T17:00:00 +0800")})} 
    it {expect(parse('5am+8')).to eq({time: Time.parse("2016-1-1T5:00:00 +0800")})} 
    it {expect(parse('2016-12-15T2300+5')).to eq({time: Time.parse("2016-12-15T23:00:00 +0500")})} 
    it {expect(parse('1730')).to eq({time: Time.parse("2016-1-1T17:30:00 +0000")})} 
    Timecop.return 
end 

WAS BISHER ich getan habe

# ensure 2 char in time format 
def ensure_2_char_in_time(t) 
    return "0#{t}" if t.to_s.length == 1 
    t.to_s 
end 


def get_time_zone_from(aTimeParams) 
    date, tzm, tzm_type = nil 

    # get date, time, timezon from given string 
    if aTimeParams.include?('-') && aTimeParams.include?('T') 
     date, time_zone = aTimeParams.split('T') 
    else 
    time_zone = aTimeParams 
    end 

    # get time, zone from given string 
    if time_zone.include?('+') 
    tzm_type = '+' 
    time_str, tzm = aTimeParams.split('+') 
    elsif time_zone.include?('-') 
    tzm_type = '-' 
    time_str, tzm = aTimeParams.split('-') 
    else 
    tzm_type = '+' 
    time_str = aTimeParams 
    end 
    date = "#{Date.today.year}-#{Date.today.month}-#{Date.today.day}" if date.blank? 

    if time_str.include?('pm') 
     hour = ensure_2_char_in_time(time_str.to_i + 12) 
     min = '00' 
    elsif time_str.include?('am') 
    hour = ensure_2_char_in_time(time_str.to_i) 
    min = '00' 
    else 
    hour = ensure_2_char_in_time(time_str.to_i/100) 
    min = ensure_2_char_in_time(time_str.to_i % 100) 
    end 

    if tzm.to_s.length <= 2 
    tzm_h = ensure_2_char_in_time tzm.to_i % 100 
    tzm_m = "00" 
    else 
    tzm_h = ensure_2_char_in_time tzm.to_i/100 
    tzm_m = ensure_2_char_in_time tzm.to_i % 100 
    end 

    { 
     time: Time.parse("#{date}T#{hour}:#{min}:00 #{tzm_type}#{tzm_h}:#{tzm_m}"), 
     tzm: (tzm_h.to_i * 60 + tzm_m.to_i) 
    } 
end 

Bitte lassen Sie mich zur weiteren Klärung wissen.

Dank

+0

Danke für den Vorschlag, lassen Sie mich das tun – przbadu

Antwort

1

Dieser Code funktioniert für die Beispiele feinen Sie erwähnt haben, und dann einige:

module FuzzyTimeParse 
    refine String do 
    # Removes the first regex match from self. 
    # Returns the matching substring if found, nil otherwise 
    def extract!(regex) 
     sub!(regex, '') 
     $& 
    end 
    end 

    refine Time.singleton_class do 
    def fuzzy_parse(date_or_time_or_something) 
     input = date_or_time_or_something.dup 

     input.extract!('am') 
     pm = input.extract!('pm') ? 12 : 0 

     timezone = input.extract!(/\s*(\+|-)\d$/).to_f || 0 

     timezone_hour = timezone.to_i 
     timezone_min = timezone * 60 % 60 

     if hour = input.extract!(/(?<![\d\:\-])\d\d?$/) 
     min = 0 
     else 
     min = input.extract!(/(?<!-)\d\d$/) || 0 
     input.extract!(':') 
     hour = input.extract!(/(?<![-\d])\d\d?$/) || 0 
     end 

     input.extract!(/T$/) 
     input.gsub!(/\s*/,'') 
     date = input.extract!(/\d\d\d\d\D?\d\d\D?\d\d/) || Time.now.strftime('%Y-%m-%d') 

     $stderr.puts "Warning : #{input} is still not parsed" unless input.empty? 
     date_time = format('%sT%02d:%02d:00 +%02d%02d', date, hour.to_i + pm, min, timezone_hour, timezone_min) 

     { time: Time.parse(date_time) } 
    end 
    end 
end 

require 'timecop' 

using FuzzyTimeParse 

describe 'convert datetime to accepted format' do 
    before do 
    Timecop.freeze(Time.local(2016, 1, 1, 2, 0, 0)) 
    end 

    it { expect(Time.fuzzy_parse('2200+5')).to eq(time: Time.parse('2016-1-1T22:00:00 +0500')) } 
    it { expect(Time.fuzzy_parse('100')).to eq(time: Time.parse('2016-1-1T01:00:00 +0000')) } 
    it { expect(Time.fuzzy_parse('1700+8')).to eq(time: Time.parse('2016-1-1T17:00:00 +0800')) } 
    it { expect(Time.fuzzy_parse('5pm+8')).to eq(time: Time.parse('2016-1-1T17:00:00 +0800')) } 
    it { expect(Time.fuzzy_parse('5am+8')).to eq(time: Time.parse('2016-1-1T5:00:00 +0800')) } 
    it { expect(Time.fuzzy_parse('2016-12-15T2300+5')).to eq(time: Time.parse('2016-12-15T23:00:00 +0500')) } 
    it { expect(Time.fuzzy_parse('2016-12-15 2300')).to eq(time: Time.parse('2016-12-15T23:00:00 +0000')) } 
    it { expect(Time.fuzzy_parse('2016-12-15 23:10 +7')).to eq(time: Time.parse('2016-12-15T23:10:00 +0700')) } 
    it { expect(Time.fuzzy_parse('1730')).to eq(time: Time.parse('2016-1-1T17:30:00 +0000')) } 
    it { expect(Time.fuzzy_parse('1210am+8')).to eq(time: Time.parse('2016-1-1T12:10:00 +0800')) } 
    it { expect(Time.fuzzy_parse('530pm+8')).to eq(time: Time.parse('2016-1-1T17:30:00 +0800')) } 
    it { expect(Time.fuzzy_parse('1730')).to eq(time: Time.parse('2016-1-1T17:30:00 +0000')) } 
    it { expect(Time.fuzzy_parse('17:30')).to eq(time: Time.parse('2016-1-1T17:30:00 +0000')) } 
    it { expect(Time.fuzzy_parse('17:30 +5')).to eq(time: Time.parse('2016-1-1T17:30:00 +0500')) } 
    it { expect(Time.fuzzy_parse('2016-12-03')).to eq(time: Time.parse('2016-12-03T00:00:00 +0000')) } 
    it { expect(Time.fuzzy_parse('2016-12-03 +2')).to eq(time: Time.parse('2016-12-03T00:00:00 +0200')) } 

    after do 
    Timecop.return 
    end 
end 

Es gibt:

16 examples, 0 failures 

Wenn Sie wollen nicht das Rad neu zu erfinden , Chronic Juwel könnte Ihnen helfen, auch wenn es scheint, dass die Zeitzone manuell definiert werden muss: Chronic.time_class = Time.zone

+0

Danke Eric für Ihre Lösung – przbadu

Verwandte Themen