2013-03-28 16 views
5

Questa domanda è relativa a this one, ma è mantenuta più generale e può essere trattata in modo indipendente.Quartz.NET - Non dovrebbe passare questo test dell'unità?

EDIT: versione quarzo è v2.0.1

Dalla mia comprensione, il seguente test unità dovrebbe passare:

[Test] 
public void Test() { 
    // run every first day of month at 14:00 hours 
    CronExpression expression = new CronExpression("0 0 14 1 * ?"); 

    // TimeZoneInfo.Local = {(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien} 
    if (!TimeZoneInfo.Local.SupportsDaylightSavingTime) { 
     return; 
    } 

    // get "summertime" period for current timezone 
    var daylightChange = TimeZone.CurrentTimeZone.GetDaylightChanges(2013); 
    // -> daylightChange.Start  {31.03.2013 02:00:00} System.DateTime 
    // -> daylightChange.End  {27.10.2013 03:00:00} System.DateTime 

    // get one startpoint before and one after begin of summertime 
    DateTimeOffset beforeSummertime = daylightChange.Start.ToUniversalTime().AddDays(-1); 
    DateTimeOffset afterSummertime = daylightChange.Start.ToUniversalTime().AddDays(1); 
    // -> beforeSummertime {30.03.2013 01:00:00 +00:00} System.DateTimeOffset 
    // -> afterSummertime {01.04.2013 01:00:00 +00:00} System.DateTimeOffset 

    DateTimeOffset? nextValidTimeFromBefore = expression.GetNextValidTimeAfter(beforeSummertime); 
    DateTimeOffset? nextValidTimeFromAfter = expression.GetNextValidTimeAfter(afterSummertime); 
    // nextValidTimeFromBefore {01.04.2013 13:00:00 +00:00} System.DateTimeOffset? 
    // nextValidTimeFromAfter {01.04.2013 12:00:00 +00:00} System.DateTimeOffset? 

    Assert.AreEqual(nextValidTimeFromBefore, nextValidTimeFromAfter); 
} 

Tuttavia (come potete vedere), il nextValidTimeFromBefore differisce da nextValidTimeFromAfter. Il risultato in nextValidTimeFromAfter è corretto. Le UTC 12:00 si verificheranno alle 14:00 durante l'estate (che è già iniziata a quel punto). Non importa se il parametro GetNextValidTimeAfter() specifica un'ora all'interno o all'esterno del periodo di ora legale.

I NextValidTimes dovrebbero essere uguali o il mio approccio è difettoso?

+1

Questo passa bene per me (io non sono nella tua TZ) e se mi basta creare un nuovo oggetto 'DaylightTime' con l'inizio e di fine che hai dettagliato (per esempio 'daylightChange = new DaylightTime (new DateTime (2013, 3, 31, 2, 0, 0), new DateTime (2013, 10, 27, 2, 0, 0), TimeSpan.MinValue)') passa pure. –

+0

Grazie, questo mi ha incoraggiato a dare un'altra occhiata alle versioni più recenti di Quartz. Ho già controllato il registro delle modifiche sul sito, che non menziona una correzione correlata. Tuttavia, quando ho guardato attraverso i commit nel repository ho notato che in realtà c'era una soluzione per questo. Aggiungerò una risposta con informazioni dettagliate. –

+0

Ho provato questo con 2.1.2.400, FWIW –

risposta

8

Ho capito che questo è un bug in Quartz.NET 2.0.1, ma è già stato risolto in 2.1.0.

Ho controllato il registro delle modifiche sul sito, che non menziona una correzione correlata. Il commento di Peter Ritchie mi ha incoraggiato a dare un'altra occhiata alle versioni più recenti di Quartz. Quando ho guardato attraverso i commit nel repository ho notato che in realtà c'era una soluzione per questo.

E 'stato risolto in versione 665: richiesta di pull

Merge # 72 da Amazing-andrew/master
questioni fuso tempo con CronExpression, calendari, CalendarIntervalTriggerImpl

La prima uscita ufficiale che contiene questa correzione è v2.1.0, che è stato taggato alla revisione 685.

Il bug si trovava in CronExpression.GetTimeAfter() (che è chiamato da CronExpression.GetNextValidTimeAfter()):

... 
d = new DateTimeOffset(year, d.Month, d.Day, d.Hour, d.Minute, d.Second, d.Offset); 

// apply the proper offset for this date (this wasn't there) 
d = new DateTimeOffset(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, this.TimeZone.GetUtcOffset(d.DateTime)); 
...