![서로 다른 서버에서 TZ 차이를 극복하는 방법은 무엇입니까?](https://linux55.com/image/53053/%EC%84%9C%EB%A1%9C%20%EB%8B%A4%EB%A5%B8%20%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C%20TZ%20%EC%B0%A8%EC%9D%B4%EB%A5%BC%20%EA%B7%B9%EB%B3%B5%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
우리는 서로 다른 시간대에 일부 서버를 보유하고 있습니다. 날짜가 포함된 table.html이 있습니다. 우리는 각 서버가 정확한 날짜를 갖기를 원하므로 다음과 같이 생각합니다.
- we should convert the time on server "A" to unix time.
- then on server "B" back from unix time to normal time.
묻다:그렇다면 일반 날짜 <-> 유닉스 시간 사이를 어떻게 변환합니까? 따라서 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>
유닉스 시간을 현지 시간으로 변환하려면:
$ 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