0
votes

Perl convertissant la date de formatage en ymd H: M

Je rencontre des problèmes pour convertir la date du Apr 9 2017 3:45:00:000AM en 2017-04-09 03:45:00

Voici ce que j'ai essayé.

use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(pattern   => '%h %d %Y %H:%M',);
$start_date = $strp->parse_datetime('Apr  9 2017  3:45:00:000AM');

imprime 2017-04-09T03:45:00 et non 2017-04-09 03:45:00 . Essayer d'obtenir une horloge de 24 heures, donc lorsque je passe AM à PM la même heure s'imprime.


7 commentaires

Le code que vous avez fourni n'imprime rien. Vous mentionnez AM / PM , mais votre exemple est avec 3:45 AM , ce qui signifie qu'il est identique au format 12 heures et 24 heures, ce qui rend votre question un peu floue. Pourriez-vous ajouter le code qui fait l'impression (il semble que vous venez d'ajouter un T supplémentaire là-dedans ...), et utiliser 3:45 PM plutôt que 3:45 AM comme exemple s'il vous plaît?


En outre, je suppose que la finale :000 avant AM en millisecondes; Est-ce correct? Si tel est le cas, seront-ils toujours 000 ou peuvent-ils être un nombre arbitraire à 3 chiffres? (la réponse ne sera pas la même dans les deux cas)


@Dada c'est mon code. C'est un copier-coller et il s'imprime J'ai oublié d'ajouter my $start_date; Mais le code est ce que j'utilise et il imprime 2017-04-09T03:45:00 . Je ne sais donc pas pourquoi il n'imprime pas pour vous. oui le :000 est en millisecondes. Oui, j'ai utilisé AM mais si vous permutez AM à PM j'obtiens le même résultat. Ce que je pouvais espérer obtenir 2017-04-09T15:45:00 pour PM. Ce que j'essaie de produire, c'est le 2017-04-09 03:45:00 pour le matin et le 2017-04-09 15:45:00 pour le PM.


1 / Votre code ne contient aucune impression, ni aucune fonction qui imprime quoi que ce soit. Veuillez fournir votre code réel. 2 / Vous n'avez pas répondu à ma question concernant les millisecondes: sont-elles toujours 000 ou pas?


print "$start_date"; et non ils ne sont pas toujours 000.


Alors ... vous ne vous souciez pas des millisecondes, ou les voulez-vous? Et vous voulez un format 24 heures, pas AM / PM, non? C'est ce que j'ai supposé dans ma réponse s'il vous plaît laissez-moi savoir si c'est faux


(Je veux dire que lorsque vous imprimez, vous ne voulez pas voir les millisecondes et voulez le format 24 heures? Voir modifier ma réponse et clarifier si nécessaire)


3 Réponses :


1
votes

Le code suivant montre comment la sortie souhaitée peut être obtenue sans aucun module

use strict;
use warnings;
use feature 'say';

use DateTime::Format::DateParse;
 
my($date, $dt);

$date = 'Apr  9 2017  3:45:00:000AM';
$date =~ s/:(\d{3}[AP]M)/.$1/;

$dt = DateTime::Format::DateParse->parse_datetime( $date );

$date = $dt;
$date =~ s/T/ /;

say $date;

Code Perl avec l'aide du module

use strict;
use warnings;
use feature 'say';

my $date   = 'Apr  9 2017  3:45:00:000AM';
my @fields = qw/month mday year hour min sec usec/;
my %months = ( Jan => 1,  Feb => 2,  Mar => 3,
               Apr => 4,  May => 5,  Jun => 6, 
               Jul => 7,  Aug => 8,  Sep => 9, 
               Oct => 10, Nov => 11, Dec => 12
            );
my %parts;

@parts{@fields} = split "[ :]+", $date;

$parts{hour} += 12 if $parts{usec} =~ /PM/;
$parts{month} = $months{ $parts{month} };

printf "%04d-%02d-%02d %02d:%02d:%02d\n", 
       @parts{qw/year month mday hour min sec/};


0 commentaires

4
votes

Mettre à jour  Voir end pour un modèle strptime pour analyser correctement le format de chaîne d'entrée affiché


Ce qui est montré travaux, â € et donc le DateTime :: Format :: strptime retourne constructeur un DateTime objet. Mais quand un objet est simplement imprimé, on obtient la stringification qui est affichée.

Vous devez donc le formater pour l'impression comme vous le souhaitez. Une manière générale est avec strftime

my $strp = DateTime::Format::Strptime->new(
    pattern => '%h %d %Y %I:%M:%S%3N%p'
);

%F et %T sont des raccourcis, voir les modèles strftime

Ou combinez les ymd base ymd et hms

say $start_date->ymd('-') . ' ' . $start_date->hms(':');

Consultez la documentation et ajustez si / au besoin. Je n'ai pas compris certains détails.


- Cela ne fonctionne que par accident dans cet exemple exact, car le modèle donné à utiliser pour l'analyse dans new est incorrect pour le format d'entrée affiché et est également incompatible avec les exigences énoncées

  • Le modèle affiché n'a pas de spécificateur de format pour les secondes, ni pour les millisecondes qui le suivent, ni pour le AM/PM - tous attendus dans la chaîne d'entrée. Donc, en général, une entrée sous la forme indiquée ne peut pas être analysée correctement avec le modèle affiché

  • Le %H correspond à 00-23 heure, donc pas à une horloge de 12 heures qui est indiquée comme prévu et qui est implicite par la présence d' AM . (Il correspond toujours à un nombre de 12 heures, mais il ne le sera pas une fois que le spécificateur de format AM / PM manquant sera ajouté.)

Le modèle dans l'OP fonctionne et analyse correctement l'entrée donnée car 03:45... se trouve être en AM, et le module utilise regex pour faire correspondre le modèle donné n'importe où dans la chaîne donnée (par défaut), donc %H:%M correspond à 03:45 et le reste de la chaîne d'entrée n'a pas d'importance. Si nous activons strict dans le constructeur, cela échouera. Consultez la documentation.

En supposant que l'entrée affichée est la bonne partie dont nous aurions besoin

say $start_date->strftime("%F %T");

Ici, %I est pour une horloge de 12 heures (1-12), %S ajouté pour les secondes et %3N pour les millisecondes (voir la page dans la documentation pour les modèles, lié ci-dessus) et %p pour AM / PM.

Le reste fonctionne alors tel quel, avec l'impression dans un format souhaité donné ci-dessus.


0 commentaires

1
votes

Il y a deux problèmes avec votre code. Tout d'abord, le modèle que vous utilisez pour analyser votre date n'est pas correct: %H est utilisé pour une heure au format 24 heures. À la place, vous devez utiliser une combinaison de %i (12 heures) et %p ( AM / PM ). Deuxièmement, pour imprimer un objet DateTime , vous devez d'abord le formater (en utilisant ->strftime ou ->ymd() par exemple).

Les millisecondes de la date sont cependant un peu un problème car strptime n'a pas d'option pour correspondre aux millisecondes. Je suggère de d'abord les supprimer de votre date, puis d'analyser la date avec strptime :

use DateTime::Format::Strptime;

my $date = 'Apr  9 2017  3:45:00:505PM';

# Removing milliseconds from date
$date =~ s/:(\d{3})(?=AM|PM)//; 
my $milliseconds = $1;

my $strp = DateTime::Format::Strptime->new(pattern => '%h %d %Y %I:%M:%S%p',);
my $start_date = $strp->parse_datetime($date);

# Taking into account the milliseconds that were removed earlier
$start_date->add(seconds => 1) if $milliseconds > 500;


say $start_date->strftime("%F %T");


0 commentaires