忽略日期范围的年份的最佳做法

时间:2009-03-02 01:51:57

标签: java groovy date jodatime

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

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

是否有关于如何做到这一点的最佳做法?我可以想到一堆hacky方法(即存储月份或日期或存储日期,只需将它们带到基准年,这样我就可以比较),但似乎可能有更好的方法。

我用Java或Groovy编写这个。

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

我找到了this question关于如何确定一个季节的季节,但是重点关注几个月,我需要更多的灵活性来包含日期。

3 个答案:

答案 0 :(得分:4)

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

你必须非常谨慎地“标准化”日期,因为闰年​​可能会导致意外问题,即试图在非闰年设置2月29日将导致问题/例外。

我已经将下面的内容放在一起了,但是这个概念将是相同的。我实际上已经测试了代码,但是就像psudo代码一样,它可能会有所帮助。

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;
        }

    }
}

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

答案 1 :(得分:2)

我认为你必须推出自己的DateRange类,虽然这是一个常见的问题,你希望已经有一个聪明的实用程序可以做到这一点。作为处理季节的一般要点,你还必须考虑到地理,这将使生活变得非常困难。在奥兹国,我们与美国相反,因此夏季从11月到2月。

答案 2 :(得分:2)

数据在哪里?如果它在数据库中,我会考虑为日期创建一个表(如OLAP中的时间维度)。然后,您可以根据某些时间维度示例中的财务季度计算季节列。 (这假设你的季节不会改变但是有固定的日期)。

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

修改:刚刚看到您对用户可配置季节日期的评论。这仍然有效,因为您可以在数据库中进行连接,包括时间维度,这可以更容易地使用Java中的数据集。