Если вы следили за развитием Станции Тау, то знаете, что мы создаем научно-фантастическую вселенную на Perl, чтобы люди могли ею наслаждаться. На момент написания этой статьи время на станции Тау 194.18/89:189 GCT.

GCT означает галактическое скоординированное время и является вариантом метрического времени. Наши разработчики программного обеспечения хотели бы, чтобы у нас было это в реальном мире, но, увы, у нас его нет.

Время GCT, указанное выше, составляет примерно 194 года и 18 дней после «Катастрофы», апокалиптического события, которое фактически служит нашей «эпохой». В году 100 дней, 100 сегментов в сутках (каждый по 14,4 минуты) и 1000 единиц в сегменте (0,864 секунды каждый).

Нам нравится тот факт, что определить отображаемое время для GCT так просто, если вы подсчитаете секунды, прошедшие с начала Катастрофы (обратите внимание, что в сутках 86 400 секунд):

my $days = sprintf "%9.5f" => $elapsed_seconds / 86_400; 
$days =~ m{^
  (?<year>\d+)
  (?<day>\d\d)
  \.
  (?<segment>\d\d)
  (?<unit>\d\d\d)
}ax;
my $gct = "$+{year}.$+{day}/$+{segment}:$+{unit} GCT";

Таким образом, для приведенного выше кода, если количество секунд, прошедших после Катастрофы, равно 1 677 792 259, мы разделим это на 86 400 и получим примерно 19 418,89189. Затем регулярное выражение соответствует «194», «18», «89» и «189», которые мы затем используем для создания нашего GCT 194.18/89:189 GCT.

Из-за неточности в нормальных датах мы не получаем точного преобразования между обычными DateTime объектами и GCT, но до сих пор мы не нашли их с отклонением более чем на секунду.

Вычислить длительность (D0.00/12.500 — это продолжительность 12 сегментов и 500 единиц) так же просто:

my $days = sprintf "%9.5f" => $duration_in_seconds / 86_400;
$days =~ m{^
  (?<years>\d+)
  (?<days>\d\d)
  \. 
  (?<segments>\d\d)
  (?<units>\d\d\d) 
}ax;
my $duration => "D$+{years}.$+{days}/$+{segments}:$+{units}";

Конечно, поскольку это означает, что нам часто нужно знать общее количество секунд, у нас есть этот неприятный кусок кода, чтобы понять это:

sub period (%args) {
     my $seconds = delete $args{seconds} // 0;
     $seconds += ( delete $args{minutes}  // 0 ) * 60;
     $seconds += ( delete $args{hours}    // 0 ) * 3_600;  
     $seconds += ( delete $args{days}     // 0 ) * 86_400;
     # solar year
     $seconds += ( delete $args{years}    // 0 ) *
 31_556_925.97474;
     $seconds += ( delete $args{units}    // 0 ) * .864;   
     $seconds += ( delete $args{segments} // 0 ) * 864;
     if ( keys %args ) {
         my $unknown = join ', ' => sort keys %args;  
         croak("Unknown keys to Veure::Util::Time::period: $unknown");
     }
     return round($seconds);
 }

Метрическое время прекрасно и легко. Обычное время отстой.

Мы хотели написать код для DBIx::Class ORM, чтобы использовать объекты GCT вместо DateTimeobjects, но обнаружили слишком много предположений об использовании DateTime в коде DBIx::Class, поэтому решили пока этого не делать. Мы даже думали немного изменить продолжительность дня. Это на самом деле довольно тривиально, если вы используете метрическое время. Поскольку марсианский день немного длиннее земного, возможно, мы сможем заставить НАСА принять метрическое время для Марса вместо марсианского скоординированного времени.

Первоначально опубликовано на taustation.space 23 марта 2017 г.