使用DateTime

时间:2016-09-06 13:01:24

标签: c# datetime

我是一名初级程序员,刚刚开始。我被赋予了一项任务,确定当前是否正在发生事件(每年都会发生一次又一次)。事件存储在数据库中,格式为月/日开始日期到月/日结束日期,但没有年份。为了使事情变得更加复杂,事件不会超过正常日历年,它们发生在一年的7月1日到明年的6月30日之间的财政年度。似乎没有办法让DateTime对象没有一年,而且我真的不想使用任意年份的方法,因为我认为从长远来看这不会有用。据我了解,我们的项目将会越来越多,根据一年中的月份和日期显示信息(或不显示信息)。鉴于当前日期,以及我知道以月/日格式表示开始日期和结束日期的事件,如何判断事件当前是否正在发生?请记住,这可能会跨越日历年的变化。如果我可以将这个功能构建到一个linq查询中,那么我甚至不会从数据库中提取我不关心的事件,那将是非常棒的,但我将采取我能做的工作。我们使用的语言是C#。感谢

很抱歉我的帖子的结构,我没有多少使用堆栈溢出 数据库中的数据结构如下:

StartDate    |  EndDate
-------------|----------
3/21         |  4/15
4/25         |  5/6
11/30        |  3/7

是的,它存储为varchar。

2 个答案:

答案 0 :(得分:3)

我强烈建议您重构数据库以便更易于查询 - 您不希望在每个查询中解析每行的字符串值。此外,您可以添加一个额外的字段来指示该事件是跨年度的,即" start"按照你的最后一个例子,在"结束"之后。所以你有类似的东西:

StartDay   StartMonth   EndDay  EndMonth  CrossYear
      21            3       15         4      False
      25            4        6         5      False
      30           11        7         3      True

此时,您可以轻松地编写合理的查询。例如:

DateTime date = ...; // Wherever you get this from

var activeEvents = db.Events.Where
    (e =>
     // Regular case
     (e.CrossYear == false &&
      (date.Month > e.StartMonth || (date.Month == e.StartMonth && date.Day >= e.StartDay)) &&
      (date.Month < e.EndMonth || (date.Month == e.EndMonth && date.Day <= e.EndDay))) ||
     // Cross-year case, basically, just invert start and end... conditions
     (e.CrossYear == true &&
      (date.Month < e.StartMonth || (date.Month == e.StartMonth && date.Day <= e.StartDay)) &&
      (date.Month > e.EndMonth || (date.Month == e.EndMonth && date.Day >= e.EndDay))));

您可以通过使用乘法将月/日转换为单个数字来表达相同的结果简单地,例如

int pseudoDayOfYear = date.Month * 100 + date.Day;
var activeEvents = db.Events.Where
    (e =>
     // Regular case
     (e.CrossYear == false &&
      pseudoDayOfYear >= e.StartMonth * 100 + e.StartDay &&
      pseudoDayOfYear <= e.EndMonth * 100 + e.EndDay) ||
     // Cross-year case
     (e.CrossYear == true &&
      pseudoDayOfYear <= e.StartMonth * 100 + e.StartDay &&
      pseudoDayOfYear >= e.EndMonth * 100 + e.EndDay));

这是有效的,因为从来没有超过100天的月份,但它有点丑陋的IMO。

答案 1 :(得分:0)

我想你可以修复数据库结构,正如许多人所说的那样。话虽如此,你 是一名初级程序员,你可能对这件事没有多少发言权。

好消息:你还有几个选择。

我从你的问题中注意到的一些事情:

  1. 您显然拥有一个包含部分日期片段的事件表,以varchar格式存储。没有年份信息。

  2. 您有一个会计年度的概念,从7月1日到6月30日 - 例如2016年7月1日 - 2017年6月30日。

  3. 基于以上两点,我认为您指的是一个包含每年重复事件的表(即每个列出的行项每年发生一次)。

  4. 现在,重新解释一下您的问题:如果当前日期以上参数,您如何判断事件即将到来,是否正在发生现在,还是已经过去了?

  5. 我认为您需要做的是以下内容:

    1. 您需要一些程序化结构来将事件数据保存在表中。因此,创建一个具有开始日期,结束日期和枚举指示符的类,以表示事件是已经过去,现在正在发生,还是正在接近(将来)。您可能还希望存储某种ID或描述。也可能将这些日期片段存储到事件对象中也是有意义的。
    2. 我认为事件表行不会是一个庞大的集合,所以使用像PetaPoco,Dapper,EF等一些ORM,你应该将表行下拉到你设计的类中。您可能需要建立一些ORM映射 - 您必须研究如何执行此操作。
    3. 使用DateTime.TryParse方法从事件表中的日期片段重建日期。只需获取片段,然后将当前年添加到片段中。因此,对于您的示例3/214/15,您可以将这些字符串扩展为3/21/20164/15/2016
    4. 将日期时间值解析为事件对象后,请放下一些代码以验证日期时间信息,以便它们符合会计年度信息。你知道风云是在七月到六月。所以看看你的开始和结束的月份部分,看看它们是否都在7月之前降落。如果他们这样做,那意味着年份部分是针对下一年的(开始和结束都是AddYears(1))。如果他们都落后,那么你知道他们是今年。现在,时髦的部分是如果开始和结束跨越FY边界。示例:5月1日开始,7月1日结束。根据FY规则,年份从7月开始,所以我们谈论的是2017年5月1日开始和2017年7月1日结束。你需要弄清楚逻辑,我希望你理解我的观点。
    5. 一旦您建立了日期时间验证,剩下的就是将开始日期与当前日期进行比较 - 如果开始日期小于或等于DateTime.Today,则意味着该事件要么 a)已启动或已完成; b)如果没有,那么事件就在将来的某个地方。如果 b)的情况属实,那么您必须根据DateTime.Today评估结束日期。如果等于或小于,则事件已完成(或将在今天完成)。如果更大,那么事件仍在进行中。
    6. 对于超级冗长的帖子感到抱歉,但我只是想让您高效地了解如何仍然可以合理有效地满足您的要求,而无需触发表重新设计。

      我常常因为一些原因而重新设计现有的桌子。其中一个主要问题是,我可能不知道该表的项目依赖关系的完整地图。例如,某些生产报告可能针对该表运行。或者Excel插件可能正在查询该表并为某个用户生成一些输出。最重要的是,如果看起来有点腥,在你再次进行重新设计之前,试着弄清楚为什么它的设计是这样的。有时,鱼腥设计的基本原理是引人注目的,有时它只是一个孤立的坏思维产品(因此可以重新设计,风险最小)。