5

我需要对一些关于季节的信息进行建模,并且需要以与年份无关的方式根据开始/结束日期来跟踪它们。即,我需要允许用户将夏季定义为介于 5 月 15 日和 9 月 10 日之间,并且在所有年份都这样做。

我需要对 isThisDateInSeason 类型进行大量检查)。所有日期操作函数(即日期、日历)似乎只适用于有效日期,即包括年份信息。

有没有关于如何做到这一点的最佳实践?我可以想到一堆hacky方法(即存储月份和日期或存储日期并将它们带到基线年份,以便我可以比较),但似乎可能有更好的方法.

我正在用 Java 或 Groovy 编写这个。

Joda-Time图书馆会在这里提供帮助吗?我没有这方面的经验,但它看起来有更大的灵活性。

我发现this question about how to identify a season from date,但它侧重于月份,我需要更多的灵活性来包括日期。

4

3 回答 3

5

如果每个用户都拥有自己的数据(即他们指定他们的季节,然后输入他们自己的信息),那么您可以将数据与季节一起作为其中的一部分存储,但是我感觉您所追求的场景是共享数据跨越众多定义不同季节的用户。

您必须非常小心地“规范化”日期,因为闰年​​可能会导致意外问题,即尝试将 2 月 29 日设置为非闰年会导致问题/异常。

我将以下内容放在一起,不幸的是它的 c# 但概念是相同的。我没有实际测试过代码,但作为伪代码它可能会有所帮助。

public class SeasonChecker
{
    public enum Season {Summer, Autumn, Winter, Spring};
    private List<SeasonRange> _seasons = new List<SeasonRange>();

    public void DefineSeason(Season season, DateTime starting, DateTime ending)
    {
        starting = starting.Date;
        ending = ending.Date;

        if(ending.Month < starting.Month)
        {
            // split into 2
            DateTime tmp_ending = new DateTime(ending.Year, 12, 31);
            DateTime tmp_starting = new DateTime(starting.Year, 1, 1);

            SeasonRange r1 = new SeasonRange() { Season = season, Starting= tmp_starting, Ending = ending };
            SeasonRange r2 = new SeasonRange() { Season = season, Starting= starting, Ending = tmp_ending };

            this._seasons.Add(r1);
            this._seasons.Add(r2);
        }
        else
        {
            SeasonRange r1 = new SeasonRange() { Season = season, Starting= starting, Ending = ending };
            this._seasons.Add(r1);
        }
    }

    public Season GetSeason(DateTime check)
    {
        foreach(SeasonRange range in _seasons)
        {
            if(range.InRange(check))
                return range.Season;
        }

        throw new ArgumentOutOfRangeException("Does not fall into any season");
    }


    private class SeasonRange
    {
        public DateTime Starting;
        public DateTime Ending;
        public Season Season;

        public bool InRange(DateTime test)
        {
            if(test.Month == Starting.Month)
            {
                if(test.Day >= Starting.Day)
                {
                    return true;
                }
            }
            else if(test.Month == Ending.Month)
            {
                if(test.Day <= Ending.Day)
                {
                    return true;
                }
            }
            else if(test.Month > Starting.Month && test.Month < Ending.Month)
            {
                return true;
            }

            return false;
        }

    }
}

请注意,上面的代码假设赛季不会在同一个月开始和结束 - 我认为这是一个相当安全的赛季!

于 2009-03-02T02:36:20.113 回答
2

我认为您必须推出自己的 DateRange 类,尽管这是一个常见的问题,您希望已经有一个聪明的工具可以做到这一点。作为处理季节的一般要点,您还必须考虑地理因素,这将使生活变得非常艰难。在奥兹国,我们与美国相反,所以夏季从 11 月持续到 2 月。

于 2009-03-02T02:27:24.127 回答
2

数据在哪里?如果它在数据库中,我会考虑为日期制作一个表(如 OLAP 中的时间维度)。然后,您可以在某些时间维度示例中为您的季节计算一个列,就像它们用于财务季度一样。(这是假设您的季节没有变化但有固定日期)。

所有“if date in season”类型检查都将预先构建,将计算季节的成本推入您的设置时间而不是运行时间。

编辑:刚刚看到您对用户可配置季节日期的评论。这仍然可以工作,因为您可以在包括时间维度的数据库中进行连接,这可能比在 Java 中更容易处理数据集。

于 2009-03-02T03:07:31.833 回答