开发者

Get last 'N' quarters in C#

Suppose the current quater is 3 and the year is 2011. How can I get the last 5 quarters

Desired output:

Q3-2011
Q2-2011
Q1-2011
Q4-2010
Q3-2010

The Q and '-' is appended.

I am trying as under

int generateQuater = 5;

            int currentQuater = 3;//GetQuarter(DateTime.Now.Month);
            int currentYear = DateTime.Now.Year;

            List<string> lstQuaterYear = new List<string>开发者_开发知识库();

            lstQuaterYear.Add(string.Concat('Q',currentQuater, '-', currentYear));

            for (int i = generateQuater; i > 0; i++)
            {
              //code to be placed   
            }

Thanks


You have to decrease your loop variable. The rest is not too difficult math. Its also not necessary to handle the first iteration in any special way:

for (int i = generateQuater; i > 0; i--)
{
    lstQuaterYear.Add(string.Format("Q{0}-{1}", currentQuater, currentYear));
    if (--currentQuater == 0)
    {
        currentQuater = 4;
        currentYear--;
    }
}


As a pure LINQ expression:

    public IEnumerable<String> GetQuarters(int start, int year, int count)
    {
        return (from q in Enumerable.Range(0, count)
                select String.Format("Q{0}-{1}", (start - q) + (((q + 1) / 4) * 4) , year - ((q + 1) / 4)));
    }

The math is somewhat ugly but does work, to use it you can just do:

foreach (String quarter in GetQuarters(3, 2011, 5))
{
   Console.WriteLine(quarter);
}


Your for loop should go from 0 to your variable, when you're increasing i.

The inner code could be something like:

currentQuarter--;
if(currentQuarter == 0)
{
  currentQuarter = 4;
  currentYear--;
}


Don't forget to refactor it :)

        int count = 5;

        int currentQuarter = GetQuarter(DateTime.Now.Month);
        int currentYear = DateTime.Now.Year;

        List<string> lstQuaterYear = new List<string>();

        for (int i = count; i > 0; i--)
        {
            lstQuaterYear.Add(string.Concat('Q', currentQuarter, '-', currentYear));
            currentQuarter--;
            if (currentQuarter == 0)
            {
                currentQuarter = 4;
                currentYear--;
            }
        }


One way is to check for year roll over and then set the quarter to 4 and decrement the year:

int quarter=3;
int year=2011;
int count=5;
for(int i=0;i<count;i++)
{
   lstQuaterYear.Add(string.Format("Q{0} {1}", quarter, year);
   quarter--;
   if(quarter==0)
   {
     quarter=4;
     year--;
   }
}

Alternatively you could calculate a totalQuartal=year+quartal-1. Then decrement it on each step. And finally use year=totalQuartal/4 and quartal=totalQuartal%4+1. But I think the first way is easier to understand.


public static IEnumerable Generate(int number, int currentYear, int currentQuarter)
{
    int counter = number;
    int quarter = currentQuarter;
    int year = currentYear;
    while (counter-- > 0)
    {
        yield return String.Format("Q{0}-{1}", year, quarter);
        quarter = quarter>1?quarter-1:4;
        year = quarter==4?year-1:year;
    }
}


Here is my version (sorry, it is in VB.NET).

The idea is to :

  • easily find out the quarter based on a date (easy : divide it by 4 ... and add 1 to avoid zeros)
  • go back in time from the current date, removing 3 month at each time
  • printout the formatted quarter

the code :

Private Shared Function GetQuarterForDate(ByVal d As DateTime) As Integer
    Return (d.Month \ 4) + 1 'integer division
End Function

Private Shared Function GetLastNQuarters(ByVal N As Integer) As IEnumerable(Of String)
    Dim myDate = DateTime.Now
    Dim res As New List(Of String)()
    Do While N > 0
        'using yield would be nicer in C# ... does not exist in VB
        res.Add(String.Format("Q{0}-{1}", GetQuarterForDate(myDate), myDate.Year))
        myDate = myDate.AddMonths(-3)
        N = N - 1
    Loop
    Return res
End Function

<TestMethod()>
Public Sub CanRetrieveQuarter()
    Dim quarters = GetLastNQuarters(5)

    For Each q In quarters
        Console.WriteLine(q)
    Next
End Sub

That last "test method" prints out :

Q3-2011
Q2-2011
Q1-2011
Q4-2010
Q3-2010


In case you should do some operations on the quarter period, like check if moment is within a quarter, you can use the Quarter class of the Time Period Library for .NET:

// ----------------------------------------------------------------------
public ITimePeriodCollection GetPastQuarters( int count )
{
  TimePeriodCollection quarters = new TimePeriodCollection();

  Quarter quarter = new Quarter();
  for ( int i = 0; i < count; i++ )
  {
    quarters.Add( quarter );
    quarter = quarter.GetPreviousQuarter();
  }

  return quarters;
} // GetPastQuarters
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜