2
votes

I'm trying to find all quarters between 2 given dates.

For example if the current date is today(15 Jan 2013) and a date in the past is 01 Jan 2012, I should be getting the following result: Dec 2012 Sep 2012 June 2012 March 2012

I can kind of keep deducting 3 months from the current date, but that is not going to be accurate as the test below denotes:

  [TestMethod]
        public void FindAllQuaters_FromAGivenDate_TillAPastDate()
        {
            var dateFinder = new FindQuarter();
            //Between Feb 2013 & Jan 2012
            var dates = dateFinder.GetAllQuarters(new DateTime(2013, 02, 01), new DateTime(2012, 01, 01)).ToList();

            Assert.IsTrue(dates.Count == 4);
            Assert.IsTrue(dates.First().Month == 12);
            Assert.IsTrue(dates.First().Year == 2012);

            Assert.IsTrue(dates.Skip(1).First().Month == 9);
            Assert.IsTrue(dates.Skip(1).First().Year == 2012);

            Assert.IsTrue(dates.Skip(2).First().Month == 6);
            Assert.IsTrue(dates.Skip(2).First().Year == 2012);

            Assert.IsTrue(dates.Skip(3).First().Month == 3);
            Assert.IsTrue(dates.Skip(3).First().Year == 2012);
        }
    }

    public class FindQuarter
    {
        public IEnumerable<DateTime> GetAllQuarters(DateTime current, DateTime past)
        {
            while (current > past)
            {
                current = current.AddMonths(-3);
                yield return current;
            }
        }
    }

How can I achieve this? The quarters are defined as March,June,September & December. I would also need the last date of that month(which I hope would be quick).

EDIT: This is not working because it keeps deducting 3 months from a given date, for example if the current date is feb 2013 and I reduce 3 months,I get Nov 2012 and not December 2012.

  • Any dates in Jan,Feb,March will belong to first quarter i.e March

  • Any dates in April,May,June will belong to second quarter i.e June

  • Any dates in July,Aug,Sep will belong to third quarter i.e September

  • Any dates in Oct,Nov,Dec will belong to fourth quarter i.e December

4
I'm sorry, maybe I'm missing something but HOW/WHY isn't it working?BlackVegetable
To what quarter does 15 December 2012 belong?Jeppe Stig Nielsen
A quarter of a year should be 3 months (12 divided by 4), not 4 months. Does the quarter called "December 2012" consist of the calendar months October 2012, November 2012, and December 2012? Just trying to understand the definitions.Jeppe Stig Nielsen

4 Answers

3
votes

This seems to work.

        public IEnumerable<DateTime> GetAllQuarters(DateTime current, DateTime past)
        {
            var curQ = (int)Math.Ceiling(current.Month / 3.0M);
            var lastQEndDate = new DateTime(current.Year, curQ * 3, 1).AddMonths(-2).AddDays(-1);

            do
            {
                yield return lastQEndDate;
                lastQEndDate = lastQEndDate.AddMonths(-3);
            } while (lastQEndDate > past);
        }
1
votes

You could use the class below i've written some time ago:

DateTime dt1 = new DateTime(2012, 1, 1);
DateTime dt2 = new DateTime(2013, 1, 15);
long countQuarters = Quarter.GetQuarters(dt1, dt2); // outputs 4

Quarter:

public class Quarter
{
    public static long GetQuarters(DateTime dt1, DateTime dt2)
    {
        double d1Quarter = GetQuarter(dt1.Month);
        double d2Quarter = GetQuarter(dt2.Month);
        double d1 = d2Quarter - d1Quarter;
        double d2 = (4 * (dt2.Year - dt1.Year));
        return Round(d1 + d2);
    }

    private static int GetQuarter(int nMonth)
    {
        if (nMonth <= 3)
            return 1;
        if (nMonth <= 6)
            return 2;
        if (nMonth <= 9)
            return 3;
        return 4;
    }

    private static long Round(double dVal)
    {
        if (dVal >= 0)
            return (long)Math.Floor(dVal);
        return (long)Math.Ceiling(dVal);
    }
}

DEMO

1
votes

I would think you could use the % operator. For example:

if (dt1.Month % 3 == 0)
{
    // it is a quarter end, else it's not. 
}
1
votes

I know this is an old thread, but here is a Lambda expression to get you this information:

    private static List<Tuple<DateTime, DateTime>> GetQuarterDates(DateTime startDate, DateTime endDate)
    {
        List<Tuple<DateTime, DateTime>> quarterDates = new List<Tuple<DateTime, DateTime>>();

        quarterDates = Enumerable.Range(0, (endDate - startDate).Days)
            .Where(x => startDate.AddMonths(x).Date == new DateTime(startDate.AddMonths(x).Year, (((startDate.AddMonths(x).Month - 1) / 3 + 1) - 1) * 3 + 1, 1))
            .Select(x => new Tuple<DateTime, DateTime>(startDate.AddMonths(x), startDate.AddMonths(x + 3).AddDays(-1)))
            .Where(x => x.Item2 <= endDate).ToList();

        return quarterDates;
    }