views:

720

answers:

3

What is the c# optimised version of the following, without using .Net's Timespan or DateTime. How would I NUnit test it?

TimeSpan ts = Date1 - Date2;
int numberOfDays = ts.Days;
A: 

You could convert the dates to ticks, substract, then convert the ticks back to days. Though exactly why can't you use TimeSpan? It's likely doing just that.

Something like this:

      DateTime a = DateTime.Now;
      DateTime b = a.AddDays(2);

      // ticks are in hns
      long ticks = b.Ticks - a.Ticks;
      long seconds = ticks / 10000000;
      long minutes = seconds / 60;
      long hours = minutes / 60;
      long days = hours / 24;

I get back "2" for days.

ctacke
A: 

Date1 and Date2 are what type? In your exameple it looks to be DateTime. You want your Date in what variable if it's not DateTime? You can always have your Date1 and Date2 in String and play with SubString() to get Year, Month and days but that would be a real pain to work with.

The optimized way to do your problem of:

TimeSpan ts = Date1 - Date2;
int numberOfDays = ts.Days;

is

DateTime Date1 = new DateTime(2008,12,01);
DateTime Date2 = new DateTime(2008,12,25);
int numberOfDayBetweenDateThatShouldBe = 25;
Assert.IsTrue((Date2-Date1).TotalDays == numberOfDayBetweenDateThatShouldBe);
Daok
A: 

thanks, this is homework (asp.net)

The task is to write an asp.net application in c# that takes 2 dates as input from the user, works out the number of days between them and displays that number back to the user. This should not use any of the in-built .net framework DateTime or TimeSpan classes.

and alas my most elegant implementation at production strength

private int CalculateDays(DateTime start, DateTime end )
{
   DateTime origin = new DateTime(); 
   return (end - origin).Days - (start - origin).Days;
}

protected void Button1_Click(object sender, EventArgs e)
{
    // Parse dates for correctness and range errors, warn as necessary
    DateTime start;
    DateTime end;

    // rough error implement error handling implementation   
    string errors = string.Empty;

         if(!DateTime.TryParse(txt_start_date.Text.Trim(), out start))   errors+="Start date was incorrect";
    else if(!DateTime.TryParse(txt_end_date.Text.Trim(), out end))   errors+= (errors.Length>0? errors+= "\n":"") + "End date was incorrect" ; 
    else if ((end.Day - start.Day) <= 0) errors+= (errors.Length>0? errors+= "\n":"" ) + "End date must be greater than the Start date" ;         //CultureInfo.InvariantCulture
    else 
    {
        Response.Write(CalculateDays(start, end)); 
    }
    Debug.Assert(errors.Length <= 0, errors); 
}

Reason being am unable to see how to do this without touching DateTime.Days at least.


edit okay thought over again and a bit of monkey work, however, no use of DateTime or Timespan anywhere

public static class PrimitiveCal
{
    // incremental total days a normal year 
    private static int[] DaysInYr = new int[] {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };

    // incremental total days in a leap year 
    private static int[] DaysInLeapYr = new int[] { 0,31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };


    public static long GetDays(int[] dt_start, int[] dt_end)
    {

        int day_diff = dt_end[0] - dt_start[0];
        int s_mth = dt_start[1];
        int e_mth = dt_end[1];
        int s_year = dt_start[2];
        int e_year = dt_end[2];
        int yr_diff = e_year - s_year;

        return day_diff + (yr_diff > 0 ?
                         // use months as boundaries, cater for leap years
                         (YrType(e_year)[e_mth - 1] +
                         (YrType(s_year)[YrType(s_year).Length - 1] - YrType(s_year)[s_mth - 1])) +
                         (yr_diff == 1 ? 0 : AddMiddleYears(s_year, e_year))

                         // get month sums in same year 
                         : YrType(e_year)[e_mth - 1] - YrType(e_year)[s_mth - 1]);
    }

    private static int AddMiddleYears(int s_year, int e_year)
    {
        int total_days = 0;
        for (int i = s_year + 1; i <= e_year - 1; i++) total_days += YrType(i)[YrType(i).Length - 1];
        return total_days;
    }

    private static int[] YrType(int year)
    {
        return (year % 4  == 0 &&  year%100!=0) || year % 400 ==0 ? DaysInLeapYr : DaysInYr;
    }
}


bizl
I just updated my answer with code. No date functions needed unless the Ticks property counts.
ctacke
Hi, I actually finally got rid all DateTime/Tickness by using int arrays. Was a killer, but it worked. I've updated the code block. Haven't been voted up yet, would've given you a +1
bizl
The first part of this should be an edit to the question, the second half should be left in this answer, but whatever.
Maxim Zaslavsky