2010-10-12 10 views
5

पर्ल में, यूनिक्स के दिनांक कमांड के आउटपुट को समय-समय पर ले जाने और यूटीसी में कनवर्ट करने के लिए कोई कुशलतापूर्वक विश्लेषण कैसे करेगा?मैं पर्ल में यूटीसी में कई समय क्षेत्रों में यूनिक्स दिनांक आउटपुट को कैसे परिवर्तित कर सकता हूं?

मैंने स्टैक ओवरफ्लो पर कई समान प्रश्न पढ़े हैं, लेकिन कुछ कई समय क्षेत्रों को पार्स करने में लगते हैं। इसके बजाय वे मैन्युअल रूप से टाइमज़ोन सेट करते हैं और इसे निश्चित रहने के लिए मानते हैं।

foreach my $input (@inputs) { 
    my $t = Time::Piece->strptime($input, 
           '%a %b %d %T %Z %Y'); 
    print $t->cdate, "\n"; 
} 

ऐसा लगता है समस्या समय क्षेत्र (% जेड) है:

# Example Input Strings: 
my @inputs = (
       'Tue Oct 12 06:31:48 EDT 2010', 
       'Tue Oct 12 07:49:54 BST 2010', 
      ); 

मैं कोई लाभ नहीं हुआ निम्नलिखित की कोशिश की। इसके अतिरिक्त, टाइम ज़ोन फ़ील्ड टाइम :: टुकड़ा में मौजूद नहीं प्रतीत होता है, जिसके लिए मुझे यूटीसी में कनवर्ट करने के लिए कस्टम कोड लिखने की आवश्यकता होगी, जो कि लगता है ... गलत।

संदर्भ: मैं टाइमस्टैम्प के लिए यूनिक्स दिनांक कमांड का उपयोग करने वाले विभिन्न स्रोतों से विरासत लॉग का विश्लेषण करने का प्रयास कर रहा हूं। आदर्श रूप से, मैं सभी टाइमस्टैम्प को यूटीसी में परिवर्तित करना चाहता हूं।

किसी भी मदद की सराहना की जाएगी।

+3

आपके पास यहां होने वाली मौलिक समस्या यह है कि 3-अक्षर टाइमज़ोन संक्षेप अद्वितीय नहीं हैं। "ईएसटी" का अर्थ इस बात पर निर्भर करता है कि आप किस देश में हैं। – cjm

+0

अस्पष्टता को इंगित करने के लिए धन्यवाद। मैं जो सही जानता हूं उसे बदल सकता हूं (EST5EDT उस लॉग के लिए सही है)। हालांकि, मुझे अभी भी यकीन नहीं है कि टाइमज़ोन निकालने के लिए कस्टम कोड लिखने के बिना टाइमज़ोन कैप्चर करना है और फिर मेरे मॉड्यूल के विकल्प में मैन्युअल रूप से समय क्षेत्र सेट करना है (डेटटाइम काफी अच्छा दिख रहा है), उम्मीद है कि मैं सही स्ट्रिंग पर मैप करता हूं। – vlee

उत्तर

5

क्या आप जानते हैं TZS को स्पष्ट करने के लिए कैसे, बस उन्हें एक प्रेषण तालिका में पॉप हैं:

use strict; use warnings; 
use DateTime::Format::Strptime(); 

my @inputs = (
    'Tue Oct 12 06:31:48 EDT 2010', 
    'Tue Oct 12 07:49:54 BST 2010', 
); 

my %tz_dispatch = (
    EDT => build_parser('EST5EDT'), 
    BST => build_parser('+0100'), 
    # ... etc 
    default => build_parser(), 
); 

for my $input (@inputs) { 
    my ($parser, $date) = parse_tz($input, %tz_dispatch); 
    print $parser->parse_datetime($date), "\n"; 
} 

sub build_parser { 
    my ($tz) = @_; 

    my %conf = (
     pattern => '%a %b %d %T %Z %Y', 
     on_error => 'croak', 
    ); 
    @conf{qw/time_zone pattern/} = ($tz, '%a %b %d %T %Y') 
    if $tz; 

    return DateTime::Format::Strptime->new(%conf); 
} 

sub parse_tz { 
    my ($date, %tz_dispatch) = @_; 
    my (@date) = split /\s/, $date; 

    my $parser = $tz_dispatch{splice @date, 4, 1}; 

    return $parser 
    ? ($parser, join ' ', @date) 
    : ($tz_dispatch{default}, $date); 
} 
+0

धन्यवाद, आपका कोड निश्चित रूप से काम करता है। हालांकि, अब मैं% Z पहचानकर्ता के बारे में अधिक उलझन में हूं। आपके कोड में, एक नया डेटटाइम :: स्वरूप :: स्ट्रिपटाइम ईडीटी के लिए बनाया गया है (EST5EDT) और बीएसटी (+0100) समय क्षेत्र, एक ही ऑब्जेक्ट का उपयोग करने और parse_datetime के साथ पूरी स्ट्रिंग को पार्स करने के बजाय। मैंने "अक्टूबर 12 08:00:00 GMT 2010" का प्रयास किया जो डिफ़ॉल्ट ऑब्जेक्ट के साथ काम करता था। हालांकि, जब मैं "ओटीसी" या "EST5EDT" डिफ़ॉल्ट obje कोशिश करें सीटी क्रोक्स "मैं टाइमज़ोन को पहचान नहीं पा रहा हूं"। मुझे लगता है कि यह व्यवहार की उम्मीद है, लेकिन मुझे यकीन नहीं है कि क्यों। मुझे आश्चर्य है कि% Z के लिए पहचानने योग्य/स्वीकार्य टाइमज़ोन तार क्या हैं। – vlee

+0

स्ट्रिपटाइम पार्सर एक स्ट्रिंग लेता है, जिसमें टाइमज़ोन शामिल है, तो पार्सर इसे डेटटाइम :: टाइमज़ोन पर पास करने का प्रयास करता है। यदि स्ट्रिंग में टाइमज़ोन शामिल नहीं है, तो पार्सर कन्स्ट्रक्टर को 'time_zone' पैरामीटर की आवश्यकता होती है। मुझे उचित, अस्पष्ट, टाइमज़ोन नामों को समझने में भी मुश्किल समय था। असल में, फॉर्म के कुछ भी '[- +] \ d {4}' काम करता है। उम्मीद है की यह मदद करेगा। –

+0

+1: यह एक अच्छा जवाब है ... – dawg

5

टाइमज़ोन पर पर्ल डेटटाइम FAQ पर एक अच्छी पृष्ठभूमि है कि अधिकांश रूपांतरणों में ईडीटी और ईएसटी का उपयोग क्यों नहीं किया जा सकता है। मुद्दा यह है कि अन्य देशों में एक समान समय क्षेत्र के साथ पूर्वी समय क्षेत्र भी होता है। ईएसटी ईडीटी अन्य सुराग के बिना संदिग्ध है।

आप other modules पर देख सकते हैं, या बस मान लें कि "ईडीटी" "ईएसटी 5ईडीटी" जैसा ही है यदि यह सच है।

+0

मैंने "$ इनपुट = ~ एस/ईडीटी/ईएसटी 5EDT /;" जोड़ा स्ट्रिपटाइम को कॉल करने से पहले, लेकिन स्ट्रिपटाइम अभी भी स्ट्रिंग को पार्स करने में विफल रहता है। इसके अतिरिक्त, मुझे अभी भी विश्वास है कि समय :: टुकड़ा अपर्याप्त है क्योंकि यह टाइमज़ोन को संग्रहीत नहीं करता है, यह केवल FORMAT स्ट्रिंग के माध्यम से पारित होने की अनुमति देता है :( – vlee

+0

हालांकि कम समय क्षेत्र नाम अस्पष्टता को इंगित करने के लिए बहुत बहुत धन्यवाद! – vlee

+1

@ vlee: आपको किसी अन्य मॉड्यूल का उपयोग करने की आवश्यकता हो सकती है। 'डेटटाइम :: प्रारूप :: *' समूह में कई सीपीएएन मॉड्यूल हैं। – dawg

1

मैं हमेशा पाया है दिनांक :: Manip :: ParseDate स्थितियों के इन प्रकार के लिए अच्छा माना जाता है।

Tue Oct 12 06:31:48 EDT 2010 == Tue Oct 12 10:31:48 2010 UTC 
Tue Oct 12 07:49:54 BST 2010 == Tue Oct 12 06:49:54 2010 UTC 

जो आप जो खोज रहे हैं होने लगते हैं:

use strict; 
use warnings qw<FATAL all>; 
use Date::Manip qw<ParseDate UnixDate>; 

my @inputs = (
    q<Tue Oct 12 06:31:48 EDT 2010>, 
    q<Tue Oct 12 07:49:54 BST 2010>, 
); 

sub date2epoch($) { 
    my $user_string = shift(); 
    my $timestamp = ParseDate($user_string); 
    my $seconds  = UnixDate($timestamp, "%s"); 
    return $seconds; 
} 

sub epoch2utc($) { 
    my $seconds = shift(); 
    return gmtime($seconds) . q< UTC>; 
} 

for my $random_date (@inputs) { 
    my $epoch_seconds = date2epoch($random_date); 
    my $normal_date = epoch2utc($epoch_seconds); 
    print "$random_date == $normal_date\n"; 
} 

जब चलाने के लिए, कि यह पैदा करता है।

0

मैं इस पर एक छोटे से देर हो रही है, लेकिन जीएनयू date ही पार्स करने की दिनांक से अच्छा है:

$ date -u -d 'Thu Oct 14 01:17:00 EDT 2010' 
Thu Oct 14 05:17:00 UTC 2010 

मैं नहीं जानता कि यह कैसे EDT अस्पष्टता को हल करता है, हालांकि।

3

यदि आप दिनांक :: समय :: स्ट्रिप्टाइम का उपयोग कर रहे हैं, तो आप ओल्सन टाइम जोन नाम के लिए %O का उपयोग कर सकते हैं और पार्सिंग से पहले मैन्युअल फ़िक्सअप कर सकते हैं।

यानी।यदि आप कि अपने इनपुट में EDT मतलब है America/New_York पता , ऐसा करते हैं: अपने समय क्षेत्र कल्पना उपयोग के लिए

$time_in =~ s{EDT}{America/New_York};

और बजाय

%a %b %d %T %Z %Y

%a %b %d %T %O %Y

+0

क्या आप जानते हैं कि उन प्रारूपित दस्तावेज कहां हैं? आप उन्हें कैसे प्राप्त करते हैं? –

0

मैं बुद्धि से सहमत हूं एच जेन्डर डेट कमांड पर। -d और -u बहुत अच्छे हैं और बहुत सी कोड लाइनों को बचाते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे