it-swarm.dev

Schnell zu JJJJ-mm-tt HH: MM: SS in Perl gelangen

Beim Schreiben von Perl-Skripten muss häufig die aktuelle Uhrzeit als Zeichenfolge mit dem Code YYYY-mm-dd HH:MM:SS (z. B. 2009-11-29 14:28:29) dargestellt werden.

Dabei gehe ich diesen recht beschwerlichen Weg:

  • man perlfunc
  • /localtime für die Suche nach Ortszeit - fünfmal wiederholen (/ + \n), um zum entsprechenden Abschnitt der Manpage zu gelangen
  • Kopieren Sie den String ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); von der Manpage in mein Skript.
  • Versuchen Sie es mit my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
  • Denken Sie daran, Gotcha # 1: Muss 1900 zu $ ​​Jahr hinzufügen, um das aktuelle Jahr zu erhalten.
  • Versuchen Sie es mit my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • Denken Sie daran, Gotcha # 2: Muss $ 1 hinzufügen, um den aktuellen Monat zu erhalten.
  • Versuchen Sie es mit my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • Scheint in Ordnung. Erledigt!

Während der oben beschriebene Prozess funktioniert, ist er alles andere als optimal. Ich bin sicher, dass es einen intelligenteren Weg gibt, also ist meine Frage einfach:

Was ist der einfachste Weg, um einen YYYY-mm-dd HH:MM:SS des aktuellen Datums/der aktuellen Uhrzeit in Perl zu erhalten?

Wobei "leicht" sowohl "leicht zu schreiben" als auch "leicht zu merken" umfasst.

58
knorv

Verwenden Sie strftime im Standardmodul POSIX . Die Argumente für strftime in der Perl-Bindung wurden so gestaltet, dass sie mit den Rückgabewerten von localtime und gmtime übereinstimmen. Vergleichen Sie

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

mit

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

Beispiel für eine Befehlszeile ist

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

oder aus einer Quelldatei wie in

use POSIX;

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

Einige Systeme unterstützen die Kurzhandbücher %F und %T nicht. Daher müssen Sie explizit mit angeben

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

oder

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

Beachten Sie, dass time beim Aufruf die aktuelle Uhrzeit zurückgibt, während $^T auf den Zeitpunkt festgelegt ist, zu dem Ihr Programm gestartet wurde. Bei gmtime ist der Rückgabewert die aktuelle Uhrzeit in GMT. Rufen Sie die Zeit in Ihrer lokalen Zeitzone mit localtime ab.

67
Greg Bacon

Was nutzt das Modul DateTime nicht, um die schmutzige Arbeit für Sie zu erledigen? Es ist leicht zu schreiben und sich zu erinnern!

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;

Sobald Sie wissen, was los ist, können Sie die temporären Werte loswerden und einige Codezeilen speichern:

use strict;
use warnings;
use DateTime;

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

Versuche dies:

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

die strftime-Methode erledigt die Arbeit effektiv für mich. Sehr einfach und effizient.


29
Vish

Time :: Piece (im Kern seit Perl 5.10) hat auch eine strftime-Funktion und überlastet standardmäßig localtime und gmtime, um Time :: Piece-Objekte zurückzugeben:

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

oder ohne die überschriebene Ortszeit:

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

Ich habe einen kleinen Test gemacht (Perl v5.20.1 unter FreeBSD in VM), der folgende Blöcke jeweils 1.000.000 mal aufruft:

EIN

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);

B

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

C

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

mit folgenden Ergebnissen:

A: 2 Sekunden

B: 11 Sekunden

C: 19 Sekunden

Dies ist natürlich kein gründlicher Test oder Benchmark, aber zumindest ist es für mich reproduzierbar. Obwohl es komplizierter ist, würde ich die erste Methode vorziehen, wenn das Generieren eines Datumsstempels häufig erforderlich ist.

Aufruf (z. B. unter FreeBSD 10.1)

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

vielleicht nicht so eine gute Idee, weil es nicht vom Betriebssystem unabhängig ist und einige Zeit in Anspruch nimmt.

Viele Grüße, Holger

4
Holger

wenn Sie nur eine vom Menschen lesbare Zeitzeichenfolge wünschen und nicht das genaue Format:

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

druckt 

Mon Apr 27 10:16:19 2015

oder was auch immer für Ihr Gebietsschema konfiguriert ist.

3
robm

Time::Piece::datetime() kann T beseitigen.

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

In vielen Fällen ist die benötigte 'aktuelle Zeit' eher $ ^ T. Dies ist die Zeit, zu der die Ausführung des Skripts begonnen hat, und zwar in ganzen Sekunden (bei einer Annahme von nur 60 Sekunden Minuten) seit der UNIX-Epoche.

Dies verhindert, dass ein früher Teil eines Skripts ein anderes Datum (oder einen anderen Sommerzeitstatus) als ein späterer Teil eines Skripts verwendet, z. B. in Abfragebedingungen und anderen abgeleiteten Werten.

Für diese Variante der 'aktuellen Zeit' kann man eine Konstante verwenden, um auch zu dokumentieren, dass sie zur Kompilierungszeit eingefroren wurde:

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

Alternative Startzeit mit höherer Auflösung:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]
1
druid62

Kurz und knapp, keine zusätzlichen Module erforderlich:

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

Die Ausgabe wäre zum Beispiel: 25.04.2017 9:30:33 Uhr

0
Off The Gold