2013-04-10 200 views
2

我有一個從數據庫加載配置的對象。我存儲上次使用日期時間字段(稱爲GroupsLastRun)運行作業的時間,並且存儲作業應該使用稱爲Captureusersandgroups的字符串字段的頻率。 Captureusersandgroups存儲三種不同類型的「每日」,「每週」和「每月」。試圖將今天的日期與一個月前的日期進行比較

基本上,我有一個循環只應該繼續,如果工作是由於運行。到目前爲止,我已經到了以下幾點:

if (configEntity.GroupsLastrun > DateTime.Now.AddDays(-1) && configEntity.Captureusersandgroups == "DAILY") continue; 
if (configEntity.GroupsLastrun > DateTime.Now.AddDays(-7) && configEntity.Captureusersandgroups == "WEEKLY") continue; 
if (configEntity.GroupsLastrun > DateTime.Now.AddDays(-30) && configEntity.Captureusersandgroups == "MONTHLY") continue; 

我敢肯定,(某些)有這個一個更好的方法,但主要是一個SQL Server開發人員,我缺乏處理這個批判性思維/工具。什麼是更好的方法或我應該學習什麼,以便我能更好地考慮這一點?

+0

它工作嗎?它看起來很好。 – 2013-04-10 05:38:46

+3

請更新您的標題http://meta.stackexchange.com/questions/10647/how-do-i-write-a-good-title – 2013-04-10 05:40:05

+0

@JacobSeleznev它的作品 - 但這似乎是一個不好的方法,不是嗎? ? – Codingo 2013-04-10 05:41:54

回答

7

的幾點:

  • 除非你想在時間的擺佈區域和夏令時轉換等,我寧願使用DateTime.UtcNowDateTime.Now(並確保你存儲 UTC的值)
  • 由於ps.s.w.g.上面提到的,它只值一次要求現在的日期/時間 - 而不是性能,我想說的重要原因是一致性。在這種情況下,它看起來像只實際使用其中一個值,但在其他情況下,我已經看到人們編寫同時使用兩個評估的條件,導致代碼在午夜運行時出現問題
  • 由於檢查條件同時確定截止日期,您已重複驗證碼。我會分開這兩個。

所以,我有這樣的代碼:

// Consider whether you actually want DateTime.UtcNow.Date 
DateTime now = DateTime.UtcNow; 

DateTime deadline; 
switch (configEntity.Captureusersandgroups) 
{ 
    case "DAILY": deadline = now.AddDays(-1); 
    case "WEEKYLY": deadline = now.AddDays(-7); 
    case "MONTHLY": deadline = now.AddMonths(-1); 
    // I'm assuming there's *always* a schedule 
    default: throw new InvalidOperationException("Invalid schedule"); 
} 
if (configEntity.GroupsLastrun > deadline) 
{ 
    continue; 
} 

注意,從減去一個月的「現在」是不一樣的「然後」添加一個月。例如,如果最後一次運行是在1月30日,則下一次運行將不會在3月1日之前使用上述代碼 - 而如果您在1月30日之前添加了一個月,則會在2月28日運行(除非您使用兩個值的日期)。仔細考慮你想要的行爲。

(作爲一個快速插上,我還建議顯然考慮到我Noda Time庫日期/時間的工作,這使得它更清晰的任何特定的值是否爲本地時間,或在某些時間段等)

+0

+1是的,'UtcNow'是一個更好的選擇 – 2013-04-10 06:11:50

3

兩點:

  1. DateTime.Now可以(潛在的)每次被稱爲時間返回不同的日期。這也不是很快。您只需調用一次即可獲得更好的一致性和輕微的性能提升。
  2. 爲了保持一致性(例如,一個月中不總是30天)和全球化(例如,並非所有文化都有7天的一週),您應該使用標準方法來添加數週和數月。請注意,單獨使用DateTime不能簡單地添加星期;您必須改用Calendar

試試這個:

var now = DateTime.UtcNow; // See Jon Skeet's answer 
var cal = CultureInfo.InvariantCulture.Calendar; 
if (configEntity.GroupsLastrun > now.AddDays(-1) && configEntity.Captureusersandgroups == "DAILY") continue; 
if (configEntity.GroupsLastrun > cal.AddWeeks(now, -1) && configEntity.Captureusersandgroups == "WEEKLY") continue; 
if (configEntity.GroupsLastrun > now.AddMonths(-1) && configEntity.Captureusersandgroups == "MONTHLY") continue; 

或者只是使用cal一切:

var now = DateTime.UtcNow; // See Jon Skeet's answer 
var cal = CultureInfo.InvariantCulture.Calendar; 
if (configEntity.GroupsLastrun > cal.AddDays(now, -1) && configEntity.Captureusersandgroups == "DAILY") continue; 
if (configEntity.GroupsLastrun > cal.AddWeeks(now, -1) && configEntity.Captureusersandgroups == "WEEKLY") continue; 
if (configEntity.GroupsLastrun > cal.AddMonths(now, -1) && configEntity.Captureusersandgroups == "MONTHLY") continue; 
+0

只需調用一次'DateTime.Now'就可以提高性能*不是IMO的重要組成部分 - 它是*一致性*提升。至於增加數週 - 你會期望增加一週與增加7天不同嗎? – 2013-04-10 05:55:38

+0

@JonSkeet如果我想讓它成爲獨立的文化,我永遠不會假設一週= 7天的代碼。參見[wikipedia:Week](http://en.wikipedia.org/wiki/Week) – 2013-04-10 05:58:24

+1

該條目開始:「一週是等於七天的時間單位」。我意識到還有其他日曆不是真實的,但是鑑於您明確使用不變文化中的日曆,無論如何,它總是會持續7天。除非OP *實際上*需要考慮非格里曆日曆(在這種情況下,蠕蟲的數量會更大),它可以大大簡化生命,以便假定一週爲7天。 – 2013-04-10 06:00:39

1

作爲一個替代方法,你可能存儲在一個enum像運行期間:

enum RunPeriod 
{ 
    Daily = 1, 
    Weekly = 7, 
    Monthly = 30 
} 

然後你就可以存儲int值,而不是string,在數據庫上。這允許您在DB側進行過濾,例如:

var configsToRun = 
    from c in _myContext.Configs 
    where EntityFunctions.AddDays(c.LastRun,(int)c.RunPeriod) > DateTime.Now); 
相關問題