Perl

如何克服不同伺服器上的 TZ 差異?

  • April 16, 2014

我們在不同的時區有幾台伺服器。我們有一個包含日期的 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
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;2014-05-23-12.23.00.000000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;2014-05-26-17.00.00.000000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;NA&lt;/td&gt;&lt;/tr&gt;

伺服器“B”:

cat table.html
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;1400840580&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;1401116400&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;NA&lt;/td&gt;&lt;/tr&gt;

ps:伺服器沒有“date”命令的“-d”參數!也許perl?

ps2:“X”是刪減數據,可以是任何東西..

ps3:有時第7列沒有任何日期,然後寫“NA”

更新:我嘗試了一個答案:

$ cat a.txt 
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;2014-05-23-12.23.00.000000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;2014-05-26-17.00.00.000000&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;NA&lt;/td&gt;&lt;/tr&gt;
$ 
$ 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 (&lt;STDIN&gt;) {
   @F = split m!(&lt;td&gt;.*&lt;/td&gt;)!;
   # Field 13 contains a potential date.
   if ($import && $F[13] =~ m!(&lt;td&gt;)([0-9]+)(\.[0-9]*&lt;/td&gt;)!) {
   # 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!(&lt;td&gt;)([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]*&lt;/td&gt;)!) {
   # 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, &lt;STDIN&gt; line 1.

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

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

我建議始終儲存 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 (&lt;STDIN&gt;) {
   @F = split m!(&lt;td&gt;.*&lt;/td&gt;)!;
   # Field 13 contains a potential date.
   if ($import && @F &gt;= 13 && $F[13] =~ m!(&lt;td&gt;)([0-9]+)(\.[0-9]*&lt;/td&gt;)!) {
       # 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 &gt;= 13 && $F[13] =~ m!(&lt;td&gt;)([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.([0-9]+)\.([0-9]+)(\.[0-9]*&lt;/td&gt;)!) {
       # Export local time to unix time
       $t = POSIX.mktime($7, $6, $5, $4, $3, $2);
       $F[13] = "$1$t$8";
   }
   $_ = "@F";
}

(警告,未經測試的程式碼!)

引用自:https://unix.stackexchange.com/questions/124844