2010-01-26 18 views
9

Geçerli saat diliminin UTC ofsetini çapraz bir platformda (Windows ve Unix'in çeşitli lezzetleri) Perl'de almam gerekiyor. UTC Ben strftime() yoluyla bunu elde etmek mümkün olmalıdır gibi görünüyorPerl'de UTC ofsetini elde etmenin en iyi yolu nedir?

ilişkin mm, ancak görünmüyor: ± ss temsil

zzzzzz: Bu biçim karşılamalıdır tutarlı ol.

Unix:

Input: perl -MPOSIX -e "print strftime(\"%z\", localtime());" 
Output: -0700 

Pencereler:

Input: perl -MPOSIX -e "print strftime(\"%z\", localtime());" 
Output: Mountain Standard Time 

o Unix ben (kapat ya da en azından bir şey) istediğim şeyi verdiğini görünürken Windows değildir. Eminim ki, Date::Time veya benzeri ile yapabilirim, ancak geniş kurulum tabanımız nedeniyle bir kullanıcının sahip olacağı garantisini veremediğim herhangi bir bağımlılığım olmamayı çok isterim.

Burada bariz bir şey eksik miyim? Şimdiden teşekkürler.

cevap

14

Time::Local trick

use Time::Local; 
@t = localtime(time); 
$gmt_offset_in_seconds = timegm(@t) - timelocal(@t); 
+2

'Time :: Local', bir çekirdek modüldür. tüm Perl 5 dağılımları. – mob

+0

Bu harika bir çözümdür; sadece ilkel bir test yaptı, ama olması gerektiği gibi çalışıyor gibi görünüyor. Teşekkürler. – Morinar

-1

Taşınabilir yol "... gmtime

$t = time; 
    @a = localtime($t); 
    @b = gmtime($t); 

    $hh = $a[2] - $b[2]; 
    $mm = $a[1] - $b[1]; 
    # in the unlikely event that localtime and gmtime are in different years 
    if ($a[5]*366+$a[4]*31+$a[3] > $b[5]*366+$b[4]*31+$b[3]) { 
     $hh += 24; 
    } elsif ($a[5]*366+$a[4]*31+$a[3] < $b[5]*366+$b[4]*31+$b[3]) { 
     $hh -= 24; 
    } 
    if ($hh < 0 && $mm > 0) { 
     $hh++; 
     $mm = 60-$mm; 
    } 
    printf "%+03d:%02d\n", $hh, $mm; 

Birisi bu zaten, 3, 4, 5 aşağılarında bir modülde uygulandığını işaret ile localtime çıktısını karşılaştırma

+0

sen hesaplama açıklayabilir eğer statment - Bir artık yılda gün sayısına göre yıl çarpın neden? Neden Ay * 31? Neden günü ekleyelim? Teşekkürler. –

+0

@Kevin Friedman - 'a [5,4,3]' ve 'B' (5,4,3) 'nin aynı günü temsil edip etmediğini görmek için yapılan bir testtir. Yıl, ay ve gününü tek bir sayı olarak birleştiriyorum, böylece üç yerine bir karşılaştırmayla başarabilirim. 366 ve 31'den daha büyük sayıları kullanabilirsiniz ve hala doğru sonucu alacaksınız. – mob

+0

Hızlı olmak istiyorsanız çarpım yerine bit alanlarını kullanmalısınız: '($ a [5] << 13) | ($ a [4] << 5) | $ a [3]'. Ayrıca, if ifadesini değiştirmek için kullanılabilecek "<=>" operatörü. – dolmen

0

olduğunu Geniş kurulum tabanımız "

Nedeniyle ilgili bir garantiye sahip olacağımı garanti edemediğim herhangi bir bağımlılık olmamayı çok isterim. Kurulumunuzda zaman (buna My :: Date :: Time) diyoruz? Örneğin,

use lib 'my-module/dependencies/'; 

use My::Date::Time; 
0

Sen localtime($t) ve gmtime($t) arasındaki farkı hesaplayabilir yapmalıdır. İşte benim sürüm mob 'ın answer esinlenmiştir:

use strict; 
use warnings;  

sub tz_offset 
{ 
    my $t = shift; 
    my @l = localtime($t); 
    my @g = gmtime($t); 

    my $minutes = ($l[2] - $g[2] + ((($l[5]<<9)|$l[7]) <=> (($g[5]<<9)|$g[7])) * 24) * 60 + $l[1] - $g[1]; 
    return $minutes unless wantarray; 
    return (int($minutes/60), $minutes % 60); 
} 

push @ARGV, time; 
foreach my $t (@ARGV) { 
    printf "%s (%d): %+03d%02u\n", scalar localtime($t), $t, tz_offset($t); 
} 
İlgili konular