سؤال

عند كتابة نصوص Perl أجد في كثير من الأحيان الحاجة إلى الحصول على الوقت الحالي ممثلاً كسلسلة منسقة كـ YYYY-mm-dd HH:MM:SS (يقول 2009-11-29 14:28:29).

من خلال القيام بذلك أجد نفسي أسلك هذا الطريق المرهق للغاية:

  • man perlfunc
  • /localtime للبحث عن التوقيت المحلي - كرر خمس مرات (/ + \n) للوصول إلى القسم ذي الصلة من الصفحة
  • انسخ السلسلة ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); من manpage إلى البرنامج النصي الخاص بي.
  • محاولة مع my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
  • تذكر مسكتك رقم 1:يجب إضافة 1900 إلى $year للحصول على العام الحالي.
  • محاولة مع my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • تذكر مسكتك رقم 2:يجب إضافة 1 إلى $mon للحصول على الشهر الحالي.
  • محاولة مع my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • يبدو طيب.منتهي!

على الرغم من أن العملية الموضحة أعلاه تعمل، إلا أنها بعيدة عن أن تكون مثالية.أنا متأكد من أن هناك طريقة أكثر ذكاءً، لذا سؤالي هو ببساطة:

ما هي أسهل طريقة للحصول على YYYY-mm-dd HH:MM:SS التاريخ/الوقت الحالي في بيرل؟

حيث تشمل كلمة "سهل" كلا من "سهل الكتابة" و"سهل التذكر".

هل كانت مفيدة؟

المحلول

يستخدم strftime في المعيار POSIX وحدة.الحجج ل strftime في ربط Perl تم تصميمها لتتوافق مع قيم الإرجاع من localtime و gmtime.يقارن

strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)

مع

my          ($sec,$min,$hour,$mday,$mon,$year,$wday,     $yday,     $isdst) = gmtime(time);

مثال على استخدام سطر الأوامر هو

$ perl -MPOSIX -le 'print strftime "%F %T", localtime $^T'

أو من ملف مصدر كما في

use POSIX;

print strftime "%F %T", localtime time;

بعض الأنظمة لا تدعم %F و %T الاختصارات، لذلك يجب أن تكون صريحًا معها

print strftime "%Y-%m-%d %H:%M:%S", localtime time;

أو

print strftime "%Y-%m-%d %H:%M:%S", gmtime time;

لاحظ أن time إرجاع الوقت الحالي عند استدعائه بينما $^T تم تثبيته على الوقت الذي بدأ فيه برنامجك.مع gmtime, ، قيمة الإرجاع هي الوقت الحالي بتوقيت جرينتش.استرجع الوقت في منطقتك الزمنية المحلية باستخدام localtime.

نصائح أخرى

ما لا يستخدم DateTime وحدة للقيام بالعمل القذر بالنسبة لك؟من السهل الكتابة و يتذكر!

use strict;
use warnings;
use DateTime;

my $dt   = DateTime->now;   # Stores current date and time as datetime object
my $date = $dt->ymd;   # Retrieves date as a string in 'yyyy-mm-dd' format
my $time = $dt->hms;   # Retrieves time as a string in 'hh:mm:ss' format

my $wanted = "$date $time";   # creates 'yyyy-mm-dd hh:mm:ss' string
print $wanted;

بمجرد معرفة ما يحدث، يمكنك التخلص من العناصر المؤقتة وحفظ بضعة أسطر من التعليمات البرمجية:

use strict;
use warnings;
use DateTime;

my $dt = DateTime->now;
print join ' ', $dt->ymd, $dt->hms;

جرب هذا:

use POSIX qw/strftime/;
print strftime('%Y-%m-%d',localtime);

ال strftime الطريقة تؤدي المهمة بشكل فعال بالنسبة لي.بسيطة جدا وفعالة.


ساعة (في النواة منذ Perl 5.10) يحتوي أيضًا على وظيفة strftime ويقوم بشكل افتراضي بتحميل زائد للتوقيت المحلي وgmtime لإرجاع كائنات Time::Piece:

use Time::Piece;
print localtime->strftime('%Y-%m-%d');

أو بدون التوقيت المحلي الذي تم تجاوزه:

use Time::Piece (); 
print Time::Piece::localtime->strftime('%F %T');

لقد أجريت اختبارًا صغيرًا (Perl v5.20.1 ضمن FreeBSD في VM) لاستدعاء الكتل التالية 1.000.000 مرة لكل منها:

أ

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);

ب

my $now = strftime('%Y%m%d%H%M%S',localtime);

ج

my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S');

بالنتائج التالية:

أ:2 ثانية

ب:11 ثانية

ج:19 ثانية

هذا بالطبع ليس اختبارًا أو معيارًا شاملاً، ولكنه على الأقل قابل للتكرار بالنسبة لي، لذلك على الرغم من أنه أكثر تعقيدًا، فإنني أفضل الطريقة الأولى إذا كان إنشاء طابع زمني مطلوبًا في كثير من الأحيان.

الدعوة (على سبيل المثال.تحت FreeBSD 10.1)

my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;

قد لا تكون فكرة جيدة لأنها ليست مستقلة عن نظام التشغيل وتستغرق بعض الوقت.

مع أطيب التحيات ، هولجر

Time::Piece::datetime() يمكن القضاء عليها T.

use Time::Piece;
print localtime->datetime(T => q{ });

إذا كنت تريد فقط سلسلة زمنية يمكن قراءتها بواسطة الإنسان وليس هذا التنسيق الدقيق:

$t = localtime;
print "$t\n";

مطبوعات

Mon Apr 27 10:16:19 2015

أو أي شيء تم تكوينه للغتك.

قصيرة وحلوة، لا حاجة لوحدات إضافية:

my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;

الإخراج على سبيل المثال سيكون:25/04/2017 الساعة 9:30:33 صباحًا

في كثير من الحالات، يكون "الوقت الحالي" المطلوب هو $^T، وهو الوقت الذي بدأ فيه تشغيل البرنامج النصي، بثواني كاملة (بافتراض 60 ثانية فقط) منذ عصر UNIX.

وهذا لمنع أن الجزء المبكر من البرنامج النصي يستخدم تاريخًا مختلفًا (أو حالة التوقيت الصيفي) عن الجزء الأحدث من البرنامج النصي، على سبيل المثال في شروط الاستعلام والقيم المشتقة الأخرى.

بالنسبة لهذا البديل من "الوقت الحالي"، يمكن للمرء استخدام ثابت، أيضًا لتوثيق أنه تم تجميده في وقت الترجمة:

use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );

وقت بدء التشغيل البديل عالي الدقة:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top