Is this the best way to represent decades with TimeSpan?
Asked Answered
B

3

6

I'm making a graph that cover "1930-1940", "1940-1950", "1950-1960", "1960-1970", ...

I want to represent this with a DateTime and a Timespan, but I'm not really sure how to make the TimeSpan, and I find it hard to verify if my timespans are correct.

Is this how I should use TimeSpan, or does it overlap? If it's overlapning then how can I fix it?

List<DateTime> list1 = new List<DateTime>();
List<TimeSpan> list2 = new List<TimeSpan>();

int startYearInt = 1930;

int times = 0;
const int intervalSize = 10;
for (int i = startYearInt; i < 2020; i += intervalSize)
{
    DateTime sYear = new DateTime(startYearInt + (intervalSize * times++), 1, 1);
    TimeSpan period = (sYear.AddYears(intervalSize)) - sYear;

    list1.Add(sYear);
    list2.Add(period); // <<-- Don't know if if this is correct?
}

EDIT: I have this too. And if My timespan is too small or to last it can give some problems.

public bool IsInsidePeriod(DateTime dt)
{
    return dt >= FromYearDateTime && dt < FromYearDateTime.Add(periodTimeSpan);
}
Bidet answered 12/3, 2012 at 16:3 Comment(8)
why don't you just represent them as ints?Calabresi
Why DateTime and TimeSpan ? All you need is n+1 DateTime values.Rockingham
A TimeSpan is simply and amount of time, not attached to any points in time (a span of 10 years is just that - it may be a span of 10 years a century ago or a millennium hence).Bohner
Because I have a method that return that a given DateTime is inside the timespan. (EDIT should write period instead of timespan)Bidet
My point is that you can't query the period variable to see what decade it belongs to or if a specific year belongs to it.Bohner
I made a edit, to show how I thought I would use the TimeSpan for that method.Bidet
Another note on the timespan issue is that all the timespans in List2 will be identical since they are all exactly 10 years. You might as well just const them all if your interval size is const.Eyewash
Thanks all for the great inputs!Bidet
M
7

You're better off creating a DateRange value type than using a DateTime and a TimeSpan like that. Look here for an example. You can then have a factory method that gives you a range for a decade: DateRange.DecadeStartingOn(1930);. This way, you raise the level of abstraction and deal with the concepts you're referring to in the code itself.

Your IsInsidePeriod is a simple operation for the DateRange:

public bool Includes(DateTime date) {
  return start <= date && date <= end;
}

(assuming both start and end are inclusive)

Now, if you only need to deal with decades, you don't really need a full DateRange class, just this:

class Decade {

  public int StartYear { get; private set; }
  public int EndYear { get { return StartYear + 9; } }

  public Decade(int startYear) {
    StartYear = startYear;
  }

  public bool Includes(DateTime date) {
    return StartYear <= date.Year && date.Year <= EndYear;
  }

  public override string ToString() {
    return string.Format("{0}-{1}", StartYear, EndYear + 1);
  }

}

Or maybe a more general YearRange.

Monaghan answered 12/3, 2012 at 16:14 Comment(2)
a Decade is a period of 10, your Decade code doesn't work :-)Apocope
@Apocope The end year of a decade is 9 years after the starting year. 10 years after would be the start of another decadeHerc
A
1

If all you are asking to do is solve your current issues then the code below works, hey I'm bored, I would however consider doing some research on DateTime ranges, comparisons (especially how the work with different TimeZones etc and intervals.

DateTime on MSDN

class Program
{   
    static void Main(string[] args)
    {
        int interval = 10;
        DateTime isInRangeDate = DateTime.UtcNow;

        for (int i = 1930; i < 2020; )
        {
            DateRange range = new DateRange(1, 1, i, interval);
            Console.WriteLine(string.Format("{0}: Is in range - {1}", range.ToString(), range.IsInsidePeriod(isInRangeDate)));


            i = range.EndDate.Year;
        }               

        Console.ReadLine();
    }  
}


public class DateRange
{
    public DateTime StartDate { get; private set; }
    public DateTime EndDate { get; private set; }

    public override string ToString()
    {
        return string.Format("{0}-{1}", this.StartDate.Year, this.EndDate.Year);
    }

    public DateRange(int day, int month, int year, int addYears)
    {
        StartDate = new DateTime(year, month, day, 0, 0, 0);
        EndDate = StartDate.AddYears(addYears);
    }

    public bool IsInsidePeriod(DateTime dt)
    {
        return ((dt.Date >= StartDate) && (dt.Date < EndDate));
    }
}
Apocope answered 12/3, 2012 at 16:43 Comment(0)
L
0

You can simplify your IsInPeriod method to something like this:

public bool IsInsidePeriod(DateTime dateToCompare, DateTime startDate, DateTime endDate)
{
    return startDate <= dateToCompare && dateToCompare < endDate;
}

As others have mentioned, TimeSpan is not buying you anything and is overcomplicating your described issue. Pay particular attention to the comparison operators. You may want either end to be exclusive rather than inclusive or vice versa.

Lazo answered 12/3, 2012 at 16:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.