Questa domanda ha già una bella answer, ma voglio dare una risposta che mostra perché calcolando la differenza in secondi è SBAGLIATO (quando stiamo utilizzando formattati/date locali piuttosto che galleggiano le date).
Trovo doloroso quanti suggerimenti suggeriscono alle persone di sottrarre secondi. (Questa domanda è stata la prima hit di Google per la mia ricerca, quindi non mi interessa quanti anni ha.)
Ho fatto quell'errore io stesso e mi sono chiesto perché l'applicazione avrebbe improvvisamente (durante il fine settimana) mostrare tempi incorrenti . Quindi spero che questo codice possa aiutare le persone (che potrebbero trovarsi di fronte a questo problema) a capire perché questo approccio è sbagliato e aiutarli a evitare questo errore.
Ecco un esempio completo , uno che non contiene "..." in un punto cruciale (perché se si inseriscono due date nello stesso fuso orario, potrebbe non essere visualizzato un errore).
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use DateTime;
# Friday, Oct 31
my $dt1 = DateTime->new(
time_zone => "America/Chicago",
year => 2014,
month => 10,
day => 31,
);
my $date1 = $dt1->strftime("%Y-%m-%d (%Z %z)");
# Monday, Nov 01
my $dt2 = $dt1->clone->set(month => 11, day => 3);
my $date2 = $dt2->strftime("%Y-%m-%d (%Z %z)");
# Friday, Mar 06
my $dt3 = DateTime->new(
time_zone => "America/Chicago",
year => 2015,
month => 3,
day => 6,
);
my $date3 = $dt3->strftime("%Y-%m-%d (%Z %z)");
# Monday, Mar 09
my $dt4 = $dt3->clone->set(day => 9);
my $date4 = $dt4->strftime("%Y-%m-%d (%Z %z)");
# CDT -> CST
print "dt1:\t$dt1 ($date1):\t".$dt1->epoch."\n";
print "dt2:\t$dt2 ($date2):\t".$dt2->epoch."\n";
my $diff1_duration = $dt2->subtract_datetime_absolute($dt1);
my $diff1_seconds = $diff1_duration->seconds;
my $diff1_seconds_days = $diff1_seconds/86400;
print "diff:\t$diff1_seconds seconds = $diff1_seconds_days days (WRONG)\n";
my $diff1_seconds_days_int = int($diff1_seconds_days);
print "int:\t$diff1_seconds_days_int days (RIGHT in this case)\n";
print "days\t".$dt2->delta_days($dt1)->days." days (RIGHT)\n";
print "\n";
# CST -> CDT
print "dt3:\t$dt3 ($date3):\t".$dt3->epoch."\n";
print "dt4:\t$dt4 ($date4):\t".$dt4->epoch."\n";
my $diff3_duration = $dt4->subtract_datetime_absolute($dt3);
my $diff3_seconds = $diff3_duration->seconds;
my $diff3_seconds_days = $diff3_seconds/86400;
print "diff:\t$diff3_seconds seconds = $diff3_seconds_days days (WRONG)\n";
my $diff3_seconds_days_int = int($diff3_seconds_days);
print "int:\t$diff3_seconds_days_int days (WRONG!!)\n";
print "days\t".$dt4->delta_days($dt3)->days." days (RIGHT)\n";
print "\n";
uscita:
dt1: 2014-10-31T00:00:00 (2014-10-31 (CDT -0500)): 1414731600
dt2: 2014-11-03T00:00:00 (2014-11-03 (CST -0600)): 1414994400
diff: 262800 seconds = 3.04166666666667 days (WRONG)
int: 3 days (RIGHT in this case)
days 3 days (RIGHT)
dt3: 2015-03-06T00:00:00 (2015-03-06 (CST -0600)): 1425621600
dt4: 2015-03-09T00:00:00 (2015-03-09 (CDT -0500)): 1425877200
diff: 255600 seconds = 2.95833333333333 days (WRONG)
int: 2 days (WRONG!!)
days 3 days (RIGHT)
Note:
- Anche in questo caso, sto usando date locali. Se utilizzi le date floating, non avrai questo problema, semplicemente perché le tue date rimangono nello stesso fuso orario.
- Sia intervalli di tempo nel mio esempio andare da venerdì a lunedi, quindi la differenza in giorni è 3, non 3.04 ... e naturalmente non 2,95 ...
- Girando il galleggiante in numero intero usando int() (come suggerito in un answer) è semplicemente sbagliato, come mostrato nell'esempio.
- Mi rendo conto che arrotondare la differenza in secondi potrebbe anche restituire risultati corretti nel mio esempio, ma mi sembra che sia ancora sbagliato. Dovresti calcolare una differenza di giorno di 2 (per un valore elevato di 2) e, poiché è un valore elevato di 2, trasformalo in 3. Quindi, se DateTime fornisce la funzionalità, utilizza DateTime.
Citando le documentation (delta_days() vs subtract_datetime()):
data vs datetime matematica
Se vi interessa soltanto la parte di data (calendario) di un datetime, si dovrebbe usare delta_md() o delta_days(), non subtract_datetime(). Ciò fornirà risultati prevedibili e non prevedibili, esenti da complicazioni relative alla DST .
Bottom line: non diff secondi se si utilizza DateTime. Se non sei sicuro di quale data utilizzare, usa DateTime, è fantastico.
non puoi semplicemente convertire le date in secondi e calcolare la differenza? – TStamper
Si prega di non ripetere l'errore di calcolare la differenza in secondi. Vedi [la mia risposta] (http://stackoverflow.com/a/26732755/664132) per un esempio. – basic6