7

Here's my code:

DateTime date1 = new DateTime(byear, bmonth, bday, 0, 0, 0);
DateTime datenow =  DateTime.Now;
DateTime date2 = datenow - date1

On the last line I am getting this error:

Error 1 Cannot implicitly convert type 'System.TimeSpan' to 'System.DateTime'

How do I subtract two dates?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062
  • 3
    The difference of two dates is not a date and time, hence the type is different. – Matti Virkkunen Apr 12 '10 at 19:18
  • 2
    Why not simply use `var` and avoid these silly 'typing' problems? – missingfaktor Apr 12 '10 at 19:18
  • Related question: http://stackoverflow.com/questions/1448976/is-timespan-unnecessary/1448990#1448990 – H H Apr 12 '10 at 19:19
  • 15
    @Rahul: Maybe not using var is a very good thing. He clearly still doesn't understand very well how things work. Using var will only hide that fact from him, which isn't that good of a thing, IMO. – devoured elysium Apr 12 '10 at 19:19
  • 1
    What is the result you expected ? Is it the age ? If so, the TimeSpan object can be use to get that. So use it :) – David Brunelle Apr 12 '10 at 19:24
  • @Rahul `var` can't cast a DateTime to a TimeSpan or vice versa. His concept of how date maths works is incorrect. A DateTime is a specific point in time, past, present or future. What should today minus yesterday equal? 1/2/0001? Doesn't make much sense. Thats why DT - DT = TS. Today minus yesterday is one day, or TimeSpan.FromDays(1), which makes much more sense. –  Apr 12 '10 at 19:36
  • 1
    Using var is a no brainer when you set it to new DateTime on the same line ... – James Westgate Apr 12 '10 at 21:25

11 Answers11

19

Well the point is that if you think of it, subtracting a date to another should not yield a date, it should yield a time span. And that is what happens when you use DateTime.Subtract().

TimeSpan timeSpan = datenow - date1; //timespan between `datenow` and `date1`

This will make your current code work.

If on the other hand you want to subtract, let's say, one year from your date, you can use:

DateTime oneYearBefore = DateTime.Now.AddYears(-1); //that is, subtracts one year
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • 3
    - 1 because `date1.Subtract(any date)` gives a `TimeSpan`, not a `DateTime`... Need to pass `Subtract()` method a `Timespan` to get a `DateTime`... otherwise, just use `AddDays( )` method. – Charles Bretana Apr 12 '10 at 19:22
  • @Charles Bretana: How would it make sense for the difference of two dates to return another date? Granted, `.Subtract` is superfluous because `-` works just fine, but I don't think it justifies a downvote... – Matti Virkkunen Apr 12 '10 at 19:26
  • @Matti, because code example as was initially given was wrong... It's now corrected, and I have removed my DV... – Charles Bretana Apr 12 '10 at 20:27
3

As already mentioned, date - date gives you a TimeSpan, not a DateTime. If you want a DateTime, use AddDays(-1) as in:

DateTime subtractedDate = date1.AddDays(-1); 
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
1

The result of a date comparison is a TimeSpan, not a DateTime value.

You want to do this:

TimeSpan result = datenow - date1;
James Westgate
  • 11,306
  • 8
  • 61
  • 68
1

.Subtract has two overloads. One accepts a DateTime and returns a TimeSpan, the other accepts a TimeSpan and returns a DateTime.

In other words, if you subtract a date from a date, you get the timespan difference. Otherwise, if you subtract a timespan from a date, you get a new date.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
1

Can you clarify what you are trying calculate? The difference between any two dates in C# or real life is a time span. If you are trying to calculate age then what you want is the timespan since their birth. Change Date2 to to

Timespan age = datenow - date1;
QueueHammer
  • 10,515
  • 12
  • 67
  • 91
1

You are correctly subtracting two dates in your code. What's going on is that you expect the difference between the two dates to be another date, and that's not the case.

As other posters have noticed, you get a TimeSpan. From your variable names I get the sense you're trying to find out someone's age.

Age is not a date, it's a duration. Read up on the TimeSpan object and you will find that it correctly expresses the idea you are looking for.

I'm not 0029-01-01 years old, I'm 29 years old. (Today is not my birthday, but assume it is for easy math.)

If you're trying to show someone's age in a control and that control wants a DateTime you are probably using the wrong control to do it.

Broam
  • 4,602
  • 1
  • 23
  • 38
1

Try using ticks...?

DateTime date1 = new DateTime(1986, 3, 16, 0, 0, 0);
DateTime datenow =  DateTime.Now;
DateTime date2 = new DateTime(datenow.Subtract(date1).Ticks);
Cipi
  • 11,055
  • 9
  • 47
  • 60
0

You are expecting the difference of two dates to be a date which is not. That being said, if you need to subtract a certain number of days or months, it can easily be done using the built in methods of the DateTime object such as .AddDays(-1), note that I used a negative number to substract, you can apply the opposite. Here is a quick example.

        DateTime now = DateTime.Now;

        // Get the date 7 days ago
        DateTime sevenDaysAgo = now.AddDays(-7);

        // Bulk: Get the date 7 days and two hours ago
        DateTime sevenDaysAndtwoHoursAgo = now.Add(-(new TimeSpan(7, 2, 0, 0)));
SubZero
  • 11
  • 2
0

TimeSpan Example:

private void Form1_Load(object sender, EventArgs e)
    {
        DateTime startdatetime = new DateTime(2001, 1, 2, 14, 30, 0);
        DateTime enddatetime = DateTime.Now;
        TimeSpan difference = enddatetime.Subtract(startdatetime);


        string sdifference = "TotalDays:" + difference.TotalDays + Environment.NewLine;
        sdifference += "TotalHours:" + difference.TotalHours + Environment.NewLine;
        sdifference += "TotalMilliseconds:" + difference.TotalMilliseconds + Environment.NewLine;
        sdifference += "TotalMinutes:" + difference.TotalMinutes + Environment.NewLine;
        sdifference += "TotalSeconds:" + difference.TotalSeconds + Environment.NewLine;
        sdifference += "Ticks:" + difference.Ticks + Environment.NewLine;            
        sdifference += "Total:" + difference.Days + " days, " + difference.Hours + " hours, " + difference.Minutes + " minutes, " + difference.Seconds + " seconds and " + difference.Milliseconds + " milliseconds.";

        TextBox TextBox1 = new TextBox();
        TextBox1.Multiline = true;
        TextBox1.Dock = DockStyle.Fill;
        TextBox1.Text = sdifference;
        this.Controls.Add(TextBox1);

    }
jhersey29
  • 959
  • 6
  • 6
0

Use this code:

DateTime? Startdate = cStartDate.GetValue<DateTime>().Date;
DateTime? Enddate = cEndDate.GetValue<DateTime>().Date;
TimeSpan diff =  Enddate.GetValue<DateTime>()- Startdate.GetValue<DateTime>() ;
txtDayNo.Text = diff.Days.GetValue<string>();
DaveShaw
  • 52,123
  • 16
  • 112
  • 141
Kumar Manish
  • 3,746
  • 3
  • 37
  • 42
-2

Not exactly an answer to your question, but I prefer using var instead of annotating the variables with types. var IMO makes code look much cleaner than otherwise.

Here's your code snippet with vars:

var date1 = new DateTime(byear, bmonth, bday, 0, 0, 0);
var datenow = DateTime.Now;
var date2 = datenow - date1;

EDIT:

For the C# developers with the var-is-bad mindset:

[ Original Post Here ]

I use var extensively. There has been criticism that this diminishes the readability of the code, but no argument to support that claim.

Admittedly, it may mean that it's not clear what type we are dealing with. So what? This is actually the point of a decoupled design. When dealing with interfaces, you are emphatically not interested in the type a variable has. var takes this much further, true, but I think that the argument remains the same from a readability point of view: The programmer shouldn't actually be interested in the type of the variable but rather in what a variable does. This is why Microsoft also calls type inference “duck typing.”

So, what does a variable do when I declare it using var? Easy, it does whatever IntelliSense tells me it does. Any reasoning about C# that ignores the IDE falls short of reality. In practice, every C# code is programmed in an IDE that supports IntelliSense.

If I am using a var declared variable and get confused what the variable is there for, there's something fundamentally wrong with my code. var is not the cause, it only makes the symptoms visible. Don't blame the messenger.

Now, the C# team has released a coding guideline stating that var should only be used to capture the result of a LINQ statement that creates an anonymous type (because here, we have no real alternative to var). Well, screw that. As long as the C# team doesn't give me a sound argument for this guideline, I am going to ignore it because in my professional and personal opinion, it's pure baloney. (Sorry; I've got no link to the guideline in question.)

Actually, there are some (superficially) good explanations on why you shouldn't use var but I still believe they are largely wrong. Take the example of “searchabililty”: the author claims that var makes it hard to search for places where MyType is used. Right. So do interfaces. Actually, why would I want to know where the class is used? I might be more interested in where it is instantiated and this will still be searchable because somewhere its constructor has to be invoked (even if this is done indirectly, the type name has to be mentioned somewhere). - Konrad Rudolph

Community
  • 1
  • 1
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • This does nothing to solve the original problem. date2, in this scenario, would not be a DateTime, it would be a TimeSpan. All this is doing is further obfuscating the already apparent lack of understanding expressed in the question. – Anthony Pegram Apr 12 '10 at 19:26
  • -1 How does var make things look cleaner? Now the reader must figure out the types of your variables instead of them being explicitly stated. "I" know that DateTime - DateTime returns TimeSpan and can use its properties later, but obviously the poster didn't. – Greg Apr 12 '10 at 19:29
  • @Anthony: What? This code compiles and does what is desired. What's wrong with it? – missingfaktor Apr 12 '10 at 19:29
  • @Greg: Type inference was added to C# to reduce the type-noise. You clearly have never worked with a dynamic language, have you? – missingfaktor Apr 12 '10 at 19:31
  • @Rahul, yes, it compiles. But does it answer the person's question? He was asking for a date, you're delivering a timespan but not revealing what it is. You've said "just use var" without explaining that the operation he's performing does not return what he thinks it does. – Anthony Pegram Apr 12 '10 at 19:32
  • @Anthony: He has just asked how to subtract two dates. He didn't say he's expecting a date as subtraction of two dates. – missingfaktor Apr 12 '10 at 19:34
  • Okay, thank you everybody. Now thanks to you guys I can finally get my Peer-Pressure badge. :) – missingfaktor Apr 12 '10 at 19:35
  • @Rahul, his code sample indicates otherwise. "Just use var" does not answer the question. – Anthony Pegram Apr 12 '10 at 19:35
  • @Anthony: To me, his code sample only indicates that he doesn't know what type the subtraction of dates should be. – missingfaktor Apr 12 '10 at 19:37
  • 1
    @Rahul Using var in Linq makes it cleaner looking instead of typing IEnumerable> all the time, but using it all the time obviously was not the intent. While it makes it faster for you to code it does not make it easier for people who have to follow your code after. – Greg Apr 12 '10 at 19:38
  • @Greg: Read Konrad's answer here: http://stackoverflow.com/questions/41479/use-of-var-keyword-in-c And I completely agree with him. – missingfaktor Apr 12 '10 at 19:40
  • @Rahul His answer falls short. I agree partly that the type returned from some interface isn't important but this isn't the same situation. Always abstracting the type from the programmer makes them understand less about what is going on. Are you really arguing that knowing less is better? I'm not even going to dive into using IDE's with no intellisense. What works for YOU on YOUR projects doesn't work in all situations or even most. I cannot stress enough how important transparent code is, especially in an environment where there is more than one programmer. – Greg Apr 12 '10 at 19:50
  • Just to be clear: var isn't bad, its just like everything else, good in moderation. Use it when it has a clear advantage. – Greg Apr 12 '10 at 19:53
  • 2
    @Greg: I had the same mindset as you before I started dabbling with functional languages like Scala and F#. In these languages (and even in C#) it is encouraged to leverage the type inference wherever possible. You will hardly see any type annotations in a F# or Haskell code. As an aside note, those languages have stronger type systems than C#'s. – missingfaktor Apr 12 '10 at 19:53
  • 2
    @Greg: Just FYI, in Visual Studio you can still see the type of the variable by hovering your mouse over the variable name. – missingfaktor Apr 12 '10 at 19:55
  • 2
    I fully agree with Rahul that var enhances the code readability to a large extent and hence should be used wherever possible. – Nikit Batale Apr 12 '10 at 20:20