web-dev-qa-db-fra.com

Comment convertir une date / heure en heure d'époque (heure unix / secondes depuis 1970) en Perl?

Étant donné une date/heure sous forme de tableau (année, mois, jour, heure, minute, seconde), comment la convertiriez-vous en heure d'époque, c'est-à-dire le nombre de secondes depuis 1970-01-01 00:00:00 GMT ?

Question bonus: si la date/l'heure est donnée sous forme de chaîne, comment la analyseriez-vous pour la première fois dans le tableau (y, m, d, h, m, s)?

42
dreeves

C'est le moyen le plus simple d'obtenir le temps Unix:

use Time::Local;
timelocal($second,$minute,$hour,$day,$month-1,$year);

Notez l'ordre inverse des arguments et janvier est le mois 0. Pour de nombreuses autres options, consultez le module DateTime de CPAN.

Quant à l'analyse, voir le module Date :: Parse du CPAN. Si vous avez vraiment besoin de faire attention à l'analyse des dates, le Date :: Manip peut être utile, bien que sa propre documentation vous en prévienne car elle transporte beaucoup de bagages (elle connaît des choses comme les affaires courantes vacances, par exemple) et d'autres solutions sont beaucoup plus rapides.

Si vous savez quelque chose sur le format de la date/des heures que vous analyserez, une simple expression régulière peut suffire, mais il vaut probablement mieux utiliser un module CPAN approprié. Par exemple, si vous savez que les dates seront toujours dans l'ordre YMDHMS, utilisez le module CPAN DateTime :: Format :: ISO8601 .


Pour ma propre référence, si rien d'autre, ci-dessous est une fonction que j'utilise pour une application où je sais que les dates seront toujours dans l'ordre YMDHMS avec tout ou partie de la partie "HMS" facultative. Il accepte tous les délimiteurs (par exemple, "2009-02-15" ou "2009.02.15"). Il renvoie le temps Unix correspondant (secondes depuis 1970-01-01 00:00:00 GMT) ou -1 s'il n'a pas pu l'analyser (ce qui signifie que vous devez être sûr que vous n'aurez jamais légitimement besoin d'analyser la date 1969- 12-31 23:59:59). Il suppose également que les années à deux chiffres XX jusqu'à "69" se réfèrent à "20XX", sinon "19XX" (par exemple, "50-02-15" signifie 2050-02-15 mais "75-02-15" signifie 1975- 02-15).

use Time::Local;

sub parsedate { 
  my($s) = @_;
  my($year, $month, $day, $hour, $minute, $second);

  if($s =~ m{^\s*(\d{1,4})\W*0*(\d{1,2})\W*0*(\d{1,2})\W*0*
                 (\d{0,2})\W*0*(\d{0,2})\W*0*(\d{0,2})}x) {
    $year = $1;  $month = $2;   $day = $3;
    $hour = $4;  $minute = $5;  $second = $6;
    $hour |= 0;  $minute |= 0;  $second |= 0;  # defaults.
    $year = ($year<100 ? ($year<70 ? 2000+$year : 1900+$year) : $year);
    return timelocal($second,$minute,$hour,$day,$month-1,$year);  
  }
  return -1;
}
20
dreeves

Si vous utilisez le module DateTime , vous pouvez appeler la méthode Epoch () sur un objet DateTime, car c'est ce que vous considérez comme l'heure Unix.

L'utilisation de DateTimes vous permet de convertir assez facilement d'Epoch en objets de date.

Alternativement, localtime et gmtime convertira une Epoch en un tableau contenant le jour, le mois et l'année, et timelocal et timegm du Time :: Local module fera le contraire, convertissant un tableau d'éléments temporels (secondes, minutes, ..., jours, mois, etc.) dans une époque.

34
SpoonMeiser

Pour analyser une date, regardez Date :: Parse dans CPAN.

17
bmdhacks

Je sais que c'est une vieille question, mais j'ai pensé offrir une autre réponse.

Time::Piece est le noyau à partir de Perl 5.9.5

Cela permet d'analyser le temps dans des formats arbitraires via la méthode strptime.

par exemple.:

my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
                              "%A %drd %b, %Y");

La partie utile est - parce que c'est un objet surchargé, vous pouvez l'utiliser pour des comparaisons numériques.

par exemple.

if ( $t < time() ) { #do something }

Ou si vous y accédez dans un contexte de chaîne:

print $t,"\n"; 

Vous recevez:

Wed Nov  3 00:00:00 1943

Il existe un tas de méthodes d'accesseur qui permettent d'autres transformations utiles basées sur le temps. https://metacpan.org/pod/Time::Piece

7
Sobrique
$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);
7
ysth

Get Date :: Manip from CPAN , puis:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

modifier:

Date :: Manip est gros et lent, mais très flexible dans l'analyse, et c'est du pur Perl. Utilisez-le si vous êtes pressé lorsque vous écrivez du code et que vous savez que vous ne serez pas pressé lorsque vous l'exécutez.

par exemple. Utilisez-le pour analyser les options de ligne de commande une fois au démarrage, mais ne l'utilisez pas pour analyser de grandes quantités de données sur un serveur Web occupé.

Voir les commentaires des auteurs .

(Merci à l'auteur du premier commentaire ci-dessous)

6
scottc

Peut-être l'un des meilleurs exemples de "Il y a plus d'une façon de le faire", avec ou sans l'aide du CPAN.

Si vous avez le contrôle sur ce que vous obtenez en tant que "date/heure", je vous suggère de suivre la route DateTime , soit en utilisant une sous-classe Date :: Time :: Format spécifique, soit en utilisant DateTime :: Format :: Strptime s'il n'y en a pas qui supporte votre format de date farfelu (voir FAQ datetime pour plus de détails). En général, Date :: Time est le chemin à parcourir si vous voulez faire quelque chose de sérieux avec le résultat: peu de cours sur CPAN sont tout aussi anal-rétentifs et obsessionnellement précis.

Si vous vous attendez à des trucs de forme libre bizarres, jetez-le à la méthode str2time () de Date :: Parse , qui vous donnera une valeur de secondes depuis Epoch, vous pourrez alors avoir votre chemin avec , sans la surcharge de Date :: Manip .

2
Penfold

Mon analyseur de datetime préféré est DateTime :: Format :: ISO8601 Une fois que cela fonctionne, vous aurez un objet DateTime, facilement convertible en secondes Epoch avec Epoch ()

2
skiphoppy

Il existe de nombreux modules de manipulation de date sur CPAN. Mon préféré est DateTime et vous pouvez utiliser les modules strptime pour analyser les dates dans des formats arbitraires. Il existe également de nombreux modules DateTime :: Format sur CPAN pour gérer les formats de date spécialisés, mais strptime est le plus générique.

2
Shlomi Fish

Pour plus d'informations, une doublure pouvant être appliquée, par exemple, !#/bin/sh scripts.

Epoch="`Perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"

N'oubliez pas d'éviter les valeurs octales!

2
Anders