On Monday 02 July 2007, Tim Duelken wrote:

> irgendwie stehe ich gerade auf dem Schlauch.
>
> Ich habe 3 Zeitwerte. Start / Ende / und Abstand.
>
> Nun will ich diese von Start bis Ende mit dem Abstand ausgeben. Also
> z.B. von 08:00 Uhr bis 10:00 Uhr in 30-Minuten Steps.
> Die Liste sollte also so aussehen:
>
> 08:00 - 08:30 - 09:00 - 09:30 - 10:00
>
> Wie mache ich das am besten? Habe da zwar jetzt ein gerüst mit
> umwandlung des gelesenen startwertes (aus DB) mit to_i und dann
> wilden Rechnereien, aber das geht doch bestimmt auch irgendwie ganz
> einfach mit .step oder so. Nur wie?


  start = Time.local(2007, 7, 2, 8)
  ende  = Time.local(2007, 7, 2, 10)

  start.to_i.step(ende.to_i, 30.minutes) do |t|
    puts Time.at(t).strftime('%H:%M')
  end

Das funktioniert, ist aber nicht schön. Was ich schreiben möchte, sieht 
so aus

  start.step(ende, 30.minutes) { |t| puts t.strftime('%H:%M') }

Mit einer kleinen Erweiterung der Time-Klasse geht auch das

  class Time
    def step(end_time, step)
      self.to_i.step(end_time.to_i, step) { |t| yield Time.at(t) }
    end
  end

Und wenn wir schon dabei sind

  class Time
    def ceil(resolution = 1.hour)
      Time.at((((self.to_i - 1) / resolution) + 1) * resolution)
    end
    
    def floor(resolution = 1.hour)
      Time.at((self.to_i / resolution) * resolution)
    end
  end

Damit könnten wir dann so etwas schreiben

  start = Time.local(2007, 7, 2, 8, 10)
  ende  = Time.local(2007, 7, 2, 9, 50)

  start.floor(30.minutes).step(ende.ceil(30.minutes), 30.minutes) do |t|
    ...
  end

Das funktioniert soweit ganz schön. 

Aber eigentlich wolltest du ja etwas haben, was sich als Enumerable 
aufzählen läßt. 

  (start.with_resolution(30.minutes)..ende).map { |t| t.strftime('%H:
%M') }.join(' - ')

Auch das geht

  class Time
    def with_resolution(res = 1.hour)
      TimeWithResolution.new(self, res)
    end
    
    private
    class TimeWithResolution
      def initialize(time, res)
        @time, @resolution = time, res
      end
      def succ
        TimeWithResolution.new(@time + @resolution, @resolution)
      end
      def method_missing(name, *args, &block)
        @time.send(name, *args, &block)
      end
    end
  end


Wer diesen Code verwendet, sollte natürlich noch Unittests schreiben.

Michael

-- 
Michael Schuerig
mailto:[EMAIL PROTECTED]
http://www.schuerig.de/michael/
_______________________________________________
rubyonrails-ug mailing list
[email protected]
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug

Antwort per Email an