Some of posts from this blog has been moved to dywicki.pl. You will be automatically redirected to new blog if you would submit comment.
New posts are published on dywicki.pl, this blog contains old content and it is not continued.

Niektóre posty z tego bloga zostały przeniesione do dywicki.pl. Zostaniesz automatycznie przekierowany jeśli bedzięsz chciał dodać komentarz.
Nowe posty sa publikowane na dywicki.pl, ten blog zawiera stare treści i nie jest kontynuowany.

Typ wyliczeniowy TimeUnit w Javie oraz klasa w PHP

Filed under Java,PHP by

Java od wersji 5.0 zawiera możliwość definiowania typów wyliczeniowych. Jednym z praktycznych przykładów zastosowania tego mechanizmu jest TimeUnit. Enum ten służy do konwertowania jednostek czasu pomiędzy różnymi wielkościami – na przykład z minut na sekundy.

import java.util.concurrent.TimeUnit;
// ...
TimeUnit.MINUTES.toSeconds(55);

Fajna sprawa – jeśli mamy do czynienia z konwersjami. Inny pożyteczny przykład to przekazywanie czasu jako argumentu:

package org.code_house.concurrent;

import java.util.Date;
import java.util.concurrent.TimeUnit;


public class Lock {
    void lock(TimeUnit unit, long value) throws InterruptedException {
        Thread.sleep(unit.toMillis(value));
    }

    public static void main(String[] args) throws Exception {
        System.out.println("before " + new Date());

        new Lock().lock(TimeUnit.SECONDS, 30);

        System.out.println("after " + new Date());
    }

}

Programista, który używa takiej klasy nie musi się więc przejmować konwertowaniem jednostek na milisekundy, które są podstawą do wywołania metody Thread.sleep.

TimeUnit obsługuje następujące wielkości:

  • nanosekundy
  • mikrosekundy
  • milisekundy
  • sekundy
  • minuty
  • godziny
  • dni

Posługując się kodem z Javy postanowiłem sobie przypomnieć nieco PHP i napisałem wersję tego typu wyliczeniowego dla PHP:

<?php
// namespace org\code_house\util;
/**
 * A simple class for converting between time units.
 * 
 * @author Łukasz Dywicki <luke@code-house.org>
 */
class TimeUnit {

    /**
     * Nanoseconds.
     */
    const NANOS     = 0;

    /**
     * Microseconds.
     */
    const MICROS    = 1;

    /**
     * Milliseconds
     */
    const MILLIS    = 2;

    /**
     * Seconds.
     */
    const SECONDS   = 3;

    /**
     * Minutes.
     */
    const MINUTES   = 4;

    /**
     * Hours.
     */
    const HOURS     = 5;

    /**
     * Days.
     */
    const DAYS      = 6;

    /**
     * Conversion table between time units.
     * @var array
     */
    private static $modifiers = array(
         self::NANOS     => 0.000000001,
         self::MICROS    => 0.000001,
         self::MILLIS    => 0.001,
         self::SECONDS   => 1,
         self::MINUTES   => 60,
         self::HOURS     => 3600,
         self::DAYS      => 86400,
    );

    /**
     * Constructs new time unit.
     * 
     * @param $type TimeUnit Time unit base.
     */
    public function __construct($type) {
        if ($type < TimeUnit::NANOS || $type > TimeUnit::DAYS) {
            throw new RuntimeException('Time unit base is out of range');
        }
        $this->type = $type;
    }

    public function toNanos($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::NANOS);
    }

    public function toMicros($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::MICROS);
    }

    public function toMilis($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::MILLIS);
    }

    public function toSeconds($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::SECONDS);
    }

    public function toMinutes($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::MINUTES);
    }

    public function toHours($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::HOURS);
    }

    public function toDays($value) {
        return TimeUnit::convert($this->type, $value, TimeUnit::DAYS);
    }

    /**
     * Convert method.
     * 
     * @param $from Time unit
     * @param $value Number of values.
     * @param $to Time unit
     * @return decimal
     */
    private final static function convert($from, $value, $to) {
        if ($from === $to) {
            return $value;
        }

        $value *= self::$modifiers[$from];
        return $value / self::$modifiers[$to];
    }
}

// przykład użycia
$unit = new TimeUnit(TimeUnit::SECONDS);
echo $unit->toMinutes(60) ."\n";

$unit = new TimeUnit(TimeUnit::HOURS);
echo $unit->toMinutes(1) ."\n";

?>

Niestety brak pól z modyfikatorami public static final w PHP uniemożliwił zastosowanie choćby czegoś podobnego do typu wyliczeniowego.. Kod klasy dla PHP jest wolnodostępny. :-)

3 responses so far

3 Responses to “Typ wyliczeniowy TimeUnit w Javie oraz klasa w PHP”

  1. matipl says:

    Powstała bardzo fajna i zgrabna klasa PHP, miło

  2. Fajne, to byłoby porządne Time API, bo taki parametr jest o tyle niewygodny, że należy przekazywać zarówno Unit jaki wartość. Już lepiej byłoby mieć TimeAmount, który w konstruktorze przyjmowałby TimeUnit i jego wartość, a następnie moglibyśmy to przekonwertować do dowolnej ilości innej jednostki.

    PS. kiedy jakieś posty na temat życia jednoosobowej firmy konsultingowej?

  3. [...] jednym z komentarzy Tomasz Bartczak zapytał o nowiny z życia takiej firmy. Tych którzy są [...]

Leave a Reply