2013-04-10 118 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); 
相关问题