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.
[sourcecode lang=“java”] import java.util.concurrent.TimeUnit; // … TimeUnit.MINUTES.toSeconds(55); [/sourcecode]
Fajna sprawa - jeśli mamy do czynienia z konwersjami. Inny pożyteczny przykład to przekazywanie czasu jako argumentu: [sourcecode lang=“java”] 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()); }
} [/sourcecode] 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: [sourcecode lang=“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";
?>[/sourcecode]
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. :-)