如何克服不同服务器上的TZ差异?

如何克服不同服务器上的TZ差异?

我们在不同时区有一些服务器。我们有一个包含日期的 table.html。我们希望每个服务器都有正确的日期,因此我们认为:

- we should convert the time on server "A" to unix time. 
- then on server "B" back from unix time to normal time. 

问:那么,我们如何在正常日期<->unix时间之间进行转换(因此就地编辑table.html?)

服务器“A”:

cat table.html
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>2014-05-23-12.23.00.000000</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>2014-05-26-17.00.00.000000</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>NA</td></tr>

服务器“B”:

cat table.html
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>1400840580</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>1401116400</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>NA</td></tr>

ps:服务器没有“date”命令的“-d”参数!也许是珀尔?
ps2:“X”是审查数据,可以是任何东西..
ps3:有时第七列中没有任何日期,然后写“NA”

更新:我尝试了一个答案:

$ cat a.txt 
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>2014-05-23-12.23.00.000000</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>2014-05-26-17.00.00.000000</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>NA</td></tr>
$ 
$ cat b.txt 
#!/usr/bin/env perl
use warnings;
use POSIX;
# Pass the option -i to import from unix time to local time.
# Without the option, export from local time to unix time.
$import = 0;
if (@ARGV && $ARGV[1] eq "-i") {$import = 1}
while (<STDIN>) {
    @F = split m!(<td>.*</td>)!;
    # Field 13 contains a potential date.
    if ($import && $F[13] =~ m!(<td>)([0-9]+)(\.[0-9]*</td>)!) {
    # Import unix time to local time
    ($s,$n,$h,$d,$m,$y,@_tail) = localtime($2);
    $F[13] = sprintf "$1%04d-%02d-%02d-$02d.%02d.%02d$3", $y, $m, $d, $h, $n, $s;
    }
    if (!$import && $F[13] =~ m!(<td>)([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]*</td>)!) {
    # Export local time to unix time
    $t = POSIX.mktime($7, $6, $5, $4, $3, $2);
    $F[13] = "$1$t$8";
    }
    $_ = "@F";
}
$ 
$ 
$ perl b.txt a.txt 
Use of uninitialized value $ARGV[1] in string eq at b.txt line 7.

Use of uninitialized value $F[13] in pattern match (m//) at b.txt line 16, <STDIN> line 1.

Use of uninitialized value $F[13] in pattern match (m//) at b.txt line 16, <STDIN> line 2.

Use of uninitialized value $F[13] in pattern match (m//) at b.txt line 16, <STDIN> line 3.
^C
$ 

答案1

我建议始终存储 GMT 日期,或者如果这对于包含时区信息的日期确实不方便的话。留下未指定的日期并不是一个好主意。

如果您坚持使用这种数据格式,Perl 是一个很好的工具,可以将本地日期与 GMT 日期相互转换。

一般来说,使用正则表达式解析 HTML 是一个坏主意,但如果输入格式受到高度限制也没关系。在我的回答中,我假设表格行始终位于一行上,就像您的示例一样。如果不是,您可能应该使用实际的 HTML 解析器 —HTML::Parser

#!/usr/bin/env perl
use warnings;
use POSIX;
# Pass the option -i to import from unix time to local time.
# Without the option, export from local time to unix time.
$import = 0;
if (@ARGV && $ARGV[0] eq "-i") {$import = 1}
while (<STDIN>) {
    @F = split m!(<td>.*</td>)!;
    # Field 13 contains a potential date.
    if ($import && @F >= 13 && $F[13] =~ m!(<td>)([0-9]+)(\.[0-9]*</td>)!) {
        # Import unix time to local time
        ($s,$n,$h,$d,$m,$y,@_tail) = localtime($2);
        $F[13] = sprintf "$1%04d-%02d-%02d-$02d.%02d.%02d$3", $y, $m, $d, $h, $n, $s;
    }
    if (!$import && @F >= 13 && $F[13] =~ m!(<td>)([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]*</td>)!) {
        # Export local time to unix time
        $t = POSIX.mktime($7, $6, $5, $4, $3, $2);
        $F[13] = "$1$t$8";
    }
    $_ = "@F";
}

(警告,未经测试的代码!)

答案2

一个perl办法:

$ perl -MTime::Local -nle 'push @day,$1 if /.*\<td\>(.*)\<\/td\>/;
END {
    for (@day) {
        if (/^\d/) {                                     
            ($y,$m,$d,$h,$mi,$s,@tail) = split("-|\\.",$_);
            print timelocal($s,$mi,$h,$d,$m-1,$y);
        }
    }
}' file
1400822580
1401098400

要就地更改文件:

$ perl -MTime::Local -i.bak -nle '$date = $1 if /.*\<td\>(.*)\<\/td\>/;
if ($date =~ /^\d/) {
    ($y,$m,$d,$h,$mi,$s,@tail) = split("-|\\.",$date);
    $t = timelocal($s,$mi,$h,$d,$m-1,$y);         
    $_ =~ s/$date/$t/e;
}' file
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>1400822580</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>1401098400</td></tr>
<tr><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>X</td><td>NA</td></tr>

要将 unix 时间转换为本地时间:

$ perl -i -nle '$unixtime = $1 if /.*\<td\>(.*)\<\/td\>/;
    if ($unixtime =~ /\d/) {
        ($s,$mi,$h,$d,$m,$y,@tail) = localtime($unixtime);
        $date = sprintf "%04d-%02d-%02d-%02d.%02d.%04d", $y+1900, $m+1, $d, $h, $mi, $s;
        $_ =~ s/$unixtime/$date/e;
    }
' file

相关内容