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

问题描述 投票:4回答:3

我需要建模一些关于季节的信息,并且需要以一年不可知的方式基于开始/结束日期跟踪它们。 即我需要允许用户将夏季定义为介于5月15日和9月10日之间,并且这些年份都是如此。

我需要做很多检查类型isThisDateInSeason)。 所有日期操作功能(即日期,日历)似乎只适用于有效日期,即包括年份信息。

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

我用Java或Groovy编写这个。

Joda-Time图书馆会帮忙吗? 我没有它的经验,但它看起来有更多的灵活性。

我发现了一个关于如何确定一个季节的问题 ,但这个问题主要关注几个月,我需要更多的灵活性来包含日期。

java groovy date jodatime
3个回答
4
投票

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

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

我已将下面的内容放在一起,不可思议的是它的c#,但概念将是相同的。 我实际上已经测试了代码,但是就像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;
        }

    }
}

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


2
投票

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


2
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.