Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C# (http://www.go4expert.com/articles/c-sharp-tutorials/)
-   -   Complete Guide to Using Date & Time in C# (http://www.go4expert.com/articles/complete-guide-using-date-time-c-sharp-t30019/)

shabbir 4Mar2014 20:59

Complete Guide to Using Date & Time in C#
 
One of the most important modules of a software application is the module that implements time and date management functionality. Time and dates are an integral part of any application be it a desktop based application, a web based application or a mobile application. Consider a scenario, where you have to store a record of a particular customer in your website and you want to sale products at a discounted price to those customers who signed-up for your ecommerce score more than a year ago. In such scenarios you will require comprehensive understanding of time and date management feature of .NET framework.

Like hundreds of different programming features, .NET framework also supports built-in date and time features for the convenience of the programmers. The System namespace of the .NET framework contains three structs that are vital for performing date and time operations in C#. In this article, we are going to explain, what these structs are and how they can be used to achieve the desired functionality.

These three structs are :
  • TimeSpan
  • DateTime
  • DateTimeOffset.

TimeSpan



TimeSpan struct performs two basic functions. It can be used to measure an interval of the time. It can also be used to represent a value of time in which case it only represents the time of the day, truncating the date. The resolution of TimeSpan is 100 nanoseconds and it can hold a maximum value of 10 million days in it. TimeSpan can be positive as well as negative.

In order to create a TimeSpan, you have three options: You can use constructors that further have 5 overloads. You can use static Form methods to obtain a value by passing single time value. And you can obtain TimeSpan object via performing arithmetic on the DateTime object which we will see later.

First, let us see how we can use constructors to create object of TimeSpan struct. We have a constructor that has five overloads as follows.
  1. new TimeSpan(4, 12, 45, 30,30); - Here we specified, the day, hours, minutes, seconds and milliseconds as the parameters.
  2. new TimeSpan(4, 12, 45, 30) - Here, the parameters are days, hours, minutes and seconds.
  3. new TimeSpan(6, 30, 50) - Here parameters are hours, minutes and seconds.
  4. new TimeSpan(1000000) - Here parameter is long Ticks of 100 nanoseconds.
  5. new TimeSpan() - If you do not pass any parameter, a stuct of TimeSpan type will be created with default value of 0.
In order to further grasp the concept that how we can use these constructors to create TimeSpan structs, has a look at our first Example for this article.

Example1
Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {       
            Console.WriteLine("\nConstructor with parameters days, hours, minutes, seconds and millisecond");
            TimeSpan time = new TimeSpan(4, 12, 45, 30,30);
            Console.WriteLine("Days: " + time.Days);
            Console.WriteLine("Hours: "+ time.Hours);
            Console.WriteLine("Minutes: " + time.Minutes);
            Console.WriteLine("Seconds" +time.Seconds);
            Console.WriteLine("Milliseconds" + time.Milliseconds);

            Console.WriteLine("\nConstructor with parameters days, hours, minutes and second.");
            Console.WriteLine(new TimeSpan(4, 12, 45, 30));

            Console.WriteLine("\nConstructor with parameters hours, minutes and second.");
            Console.WriteLine(new TimeSpan(6, 30, 50));

            Console.WriteLine("\nConstructor with parameters long ticks of 100ns.");
            Console.WriteLine(new TimeSpan(1000000));

          Console.WriteLine("Unparameterized Constructor : " + new TimeSpan());
          Console.ReadLine();
        }
    }
}

In Example1, we started off by declaring a struct variable time of type TimeSpan, we passed it a struct using a constructor that takes five parameters. We passed some value to the constructor parameters in order to have a struct that have some predefined values. Next, we simply displayed the variables days, hours, minutes, seconds and milliseconds of the time variable to show that it actually contains the values that we passed to it through constructor.

Similarly, in the following lines of code we first called constructor that takes four parameters, excluding the milliseconds from the previous one. The parameter that takes three parameters is the one which takes hours, minutes and seconds, excluding both the days and milliseconds. The parameter that takes one parameter is the one which takes time ticks; they are expressed in terms of nanoseconds. And lastly, we have a constructor in our code which takes no parameter but returns struct. By default this TimeSpan struct contains time 0. We have displayed all of these constructors using Console.WritLine method. You will see that the output will be displayed in proper time format i.e Hours: Minutes and Seconds etc. The output of the code in Example1 is as follows.

Output1

http://imgs.g4estatic.com/c-sharp/date-time/output1.png

Apart from using these constructors, you can also use static methods that allow you to declare a time interval in the form of single unit such as days, hours minutes or seconds. In order to get a TimeSpan of days, minutes or seconds etc. you can use following static methods.
  1. TimeSpan.FromDays(10) returns TimeSpan struct with value 10 days
  2. TimeSpan.FromHours(12) returns TimeSpan struct with value 12 hours
  3. TimeSpan.FromMinutes(30) returns TimeSpan struct with value 30 minutes
  4. TimeSpan.FromSeconds(45) returns TimeSpan struct with value 45 seconds
  5. TimeSpan.FromMilliseconds(40) returns TimeSpan struct with value 40 milliseconds
Good thing about these methods is that you can overload + and – operators as well as < and > operators on these structs. For example If you write
Code:

TimeSpan.FromDays(10)  +  TimeSpan.FromHours(12);
The resultant TimeSpan struct would have a value of 10 days and 12 hours. Now we can also print the value of the days, hours, minutes and seconds in the resultant TimeSpan. We will explain the concept of static ‘From’ methods of the TimeSpan struct in the following example. Have a look at Example2.

Example2
Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("\n*********************************\nDeclaring TimeSpan using static methods.\n");
            Console.WriteLine("Number of days: " +TimeSpan.FromDays(10));
            Console.WriteLine("Number of hours: " + TimeSpan.FromHours(12));
            Console.WriteLine("Number of minutes: " + TimeSpan.FromMinutes(30));
            Console.WriteLine("Number of seconds: " + TimeSpan.FromSeconds(45));
            Console.WriteLine("Number of milliseconds: " + TimeSpan.FromMilliseconds(40));

            Console.WriteLine("\n*********************************\nApplying Operator overloading on TimeSpan.\n");
            TimeSpan time = TimeSpan.FromDays(20) - TimeSpan.FromSeconds(2);
            Console.WriteLine("Days: " + time.Days);
            Console.WriteLine("Hours: " + time.Hours);
            Console.WriteLine("Minutes: " + time.Minutes);
            Console.WriteLine("Seconds" + time.Seconds);

            Console.ReadLine();
        }
    }
}

In Example2, we began by declaring static “From” methods of TimeSpan structs. We called FromDays, FromHours, FromMinutes and FromSeconds methods and have printed that using Console.WriteLine. When you will compile the code and see the output you will find that FromDays method would only display day, leaving rest of the values of time such as hours and minutes to zero. Similarly, FromHours method would only display the hours.

Next, what we have done is that we subtracted 2 seconds using FromSeconds(2) method from 20 days that we got by calling FromDays(20). We performed subtraction between the days and second using overloaded minus ‘-’ operator that is built-in for the TimeSpan structs. Now, when you subtract 2 seconds from 20 days, you should be left with 19 days, 23 hours, 59 minutes and 58 seconds. So, though you have one TimeSpan struct which is representing time in days and one which expresses time in seconds, but when you subtract seconds from the days you, the returning TimeSpan struct would have value of time from dayss unit up to the second’s unit. Therefore, in next lines we displayed the values of days, hours, minutes and seconds, which will contain values according to our expectations. To verify the results, look at the output of the Example2.

Ouput2

http://imgs.g4estatic.com/c-sharp/date-time/output2.png

A very interesting expect of TimeSpan class is that, you can also describe the total time interval in single unit i.e. days, minutes or hours using TotalDays, TotalHours etc. These are the static functions that give you time span in terms of single unit. For example, if you have a TimeSpan of 10 days and 12 hours. When you call TotalDays method on that TimeSpan struct’s variable, it will evaluate to 10.5 days because 12 hour means 0.5 days. Similarly, if you want to get total number of hours, you can call TotalHours static method, it will evaluate to (10 x 24) + 12 hours, which is equal to 252 hours. Same is the case for seconds and minutes. To have a practical overview of how TotalDays, TotalHours and similar methods work in C#, have a look at our third example of this tutorial.

Example3
Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("\n*********************************\nGetting total values of days, hours using Total functions.\n");
            TimeSpan time = TimeSpan.FromDays(10) + TimeSpan.FromHours(12);
            Console.WriteLine("Days: " + time.TotalDays);
            Console.WriteLine("Hours: " + time.TotalHours);
            Console.WriteLine("Minutes: " + time.TotalMinutes);
            Console.WriteLine("Seconds: " + time.TotalSeconds);

            Console.ReadLine();
        }
    }
}

In the above code, we simply used operator overloading to add two TimeSpans: One in terms of days and the other in terms of hours. We stored the result in a variable time and then we called, TotalDays, TotalHours, TotalMinutes and TotalSeconds static methods of the TimeSpan struct. When you compile this code and observe its output, you will find that it TotalDays displays 10.5 and TotalHours would display 252 as we discussed earlier. The output of this code is as follows.

Output3

http://imgs.g4estatic.com/c-sharp/date-time/output3.png

At the start of the article we mentioned that apart from holding time interval, TimeSpan struct can also hold a particular value of time. For instance you can store the current time of the system in TimeSpan struct. We will show this with the help of another example, where you will fetch the current system time and display it on the screen. Have a look at the fourth example.

Example4

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("\n*********************************\nGetting current system time.\n");
            TimeSpan time2 = DateTime.Now.TimeOfDay;
            Console.WriteLine(time2);
            Console.ReadLine();
        }
    }
}

The example is straight forward, we got the current time of the day using DateTime.Now.TimeOfDay and stored it in a variable, and then we displayed the variable it shows the current time of the system in terms of hours, minutes, seconds and milliseconds. The output of Example4 is as follows.

Output4

http://imgs.g4estatic.com/c-sharp/date-time/output4.png

DateTime



Another extremely important struct that belongs to the System namespace is the DateTime. DateTime along with TimeSpan allows you to manage virtually every situation where you need to handle time. A variant of DateTime struct, named DateTimeOffSet was introduced in .NET framework 3.5. DateTimeOffSet differs from DateTime struct in a way that it also allows users to store the UTC offset in a variable along with the time. This helps developers to efficiently perform time comparison operations if application is being run in regions with different time zones. Here an important thing to note is that both the DateTime and DateTimeOffSet structs are immutable. Also, the resolution of both the DateTime struct and the DateTimeOffSet struct is 100 ns and they can store a date between 0001 and 9999 years.

Now, let’s discuss how we can construct a DateTime struct. Basically, DateTime struct’s constructor has 12 overloads in .NET framework 4. The most important overloads are as follows.
  1. new DateTime(2014, 3, 1) - Here the parameters are year, month and the day. Here if you don’t specify the time, the compiler will assume the time at 00:00:00 midnight or 12:00:00 am for that day.
  2. new DateTime(2014, 3, 1, 13, 15, 30, 45) - Here the first three parameters are the same i.e. year, month and day, followed by hour, minute, second and millisecond.
Let us explain with the help of an example that how we can implement DateTime struct and how can we use it in our application. Have a look at the 5th example for this article.

Example5

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("\n*********************************\nDeclaring & Initializing DateTime struct.\n");

            DateTime date = new DateTime(2014, 3, 1);
            Console.WriteLine(date);

            date = new DateTime(2014, 3, 1, 13, 15, 30, 45);
            Console.WriteLine(date);

            Console.ReadLine();
        }
    }
}

In this example we have initialized date variable of DateTime struct twice; one using the date constructor and once using the overloaded constructor where we specified time as well. An interesting thing to note here is that we have specified 13 as parameter as hour. When we compile this code, you will see that in output it will automatically convert 13 to 1 pm which shows that by default, DateTime struct deals with time in 12 hour format. The output of Example5 is as follows.

Overloading a DateTime construct with calendar



A DateTime struct can also be overloaded if we pass a calendar object as a fourth parameter to it. For instance, you can declare a DateTime struct as follows:

Code:

  DateTime date = new DateTime(1434, 2, 18, new System.Globalization.HijriCalendar());
Here look at the fourth argument; it is a calendar object of System.Globalization namespace. In the above line of code, we have used a hijri (Islamic) calendar. You can explore and use other calendars as well according to your needs. Let us take help of a working example to explain a very interesting aspect of constructing a DateTime struct using a calendar object. Have a look at Example6.

Example6

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("Declaring & Initializing DateTime struct with calender.\n");

            DateTime date = new DateTime(1434, 2, 18, new System.Globalization.HijriCalendar());
            Console.WriteLine(date);

            Console.ReadLine();
        }
    }
}

If you compile the above code you will see the following output.

Output6

http://imgs.g4estatic.com/c-sharp/date-time/output6.png

You must be wondering that you specified the values in hijri calendar yet the date has been displayed in Gregorian calendar format. The reason is that the format of the output of DateTime struct depends upon the calendar settings in the control panel of your system. By default the calendar of the system is set to Gregorian, hence the compiler converts the date into Gregorian format despite the fact that you have constructed the DateTime struct by passing it a calendar other than Gregorian and then displays it on the output screen.

DateTimeOffset



DateTimeOffset as aforementioned was included in the .NET framework 3.5 onwards. DateTimeOffset is similar to DateTime struct in all respects except that it takes an additional parameter i.e Offset which is useful for identifying the time zones and handling scenarios where application is required to be run on different regions. DateTimeOffset has seven constructors, however we will discuss two of the most important ways in which you can construct a DateTimeOffset struct.
  1. DateTimeOffset date = new DateTimeOffset(2014, 3, 3, 14, 30, 30, TimeSpan.FromMinutes(60)); - The above method is similar to the DateTime construct but you can see that there is one additional parameter TimeSpan, we have passed it TimeSpan of 60 minutes which means that this time zone is +1 hour UTC time. By default UTC time zone is considered as standard
  2. DateTimeOffset date3 = new DateTimeOffset(date2, offset) - Have a look at the above lines of code, it is extremely interesting to know that you can also use an existing DateTime struct and pass it as a first parameter to DateTimeOffset constructor followed by the TimeSpan.
In our second example, I am going to show you that how you can use the above two ways to construct a DateTimeOffset struct in your application. Have a look at Example7.

Example7

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
            Console.WriteLine("Declaring & Initializing DateTimeOffset\n");


            DateTimeOffset date = new DateTimeOffset(2014, 3, 3, 14, 30, 30, TimeSpan.FromMinutes(60));
            Console.WriteLine(date);

            DateTime date2 = new DateTime(2014, 3, 3);
            TimeSpan offset = TimeSpan.FromHours(2);

            DateTimeOffset date3 = new DateTimeOffset(date2, offset);

            Console.WriteLine(date3);

            Console.ReadLine();
        }
    }
}

Pay attention to the code in Example7, here first of all we declared a DateTimeOffset struct date and used normal constructor where we directly passed the values of years, months, days, hours, minutes and seconds respectively, followed by the TimeSpan. Next, we declared a DateTime struct date2 and initialized it with some values. Then we initialized a TimeSet construct offset and stored 2 hours in it using FromHours static method. Then we initialized another DateTimeOffset struct date3 and used overloaded constructor where we passed previously initialized DateTime struct date2 as first argument and then we passed previously initialized TimeSpan struct ‘offset’ to the constructor. We then, displayed the value of date3 struct. First look at the output of the Example7 and then I will explain that what is happening there.

Output7

http://imgs.g4estatic.com/c-sharp/date-time/output7.png

You can see that the first output is DateTimeOffset struct ‘date’ which is simply a date that we mentioned, followed by a time and then ‘+01:00’ which means that the time is +1 hour of the standard UTC time because we passed TimeSpan of 60 minutes which is equal to 1 hour. The next output is of DateTimeOffset ‘date3’ where we passed DateTime struct date2 and TimeSpan struct offset which was of 2 hours. You can see that in the output after the date, a UTC offset of +2 is displayed.

While specifying a TimeSpan offset, you must keep one thing in mind that the value you are passing should be equal whole number of minutes otherwise the compiler will throw an exception.

Displaying the current system date & time



Using the DateTime and DateTimeOffset, the current date and time of the system, according to the default system calendar which is set through control panel can be obtained. Following are the static methods that help fetch the current date and time of the system.
  1. DateTime.Now Returns current date as well as time except UTC offset
  2. DateTime.Today Returns only the current date, not time.
  3. DateTimeOffset.Now Returns the current date as well as time plus UTC offset.
  4. DateTime.UtcNow Returns the Current date as well as the UTC offset.
  5. DateTimeOffset.UtcNow Returns the Current date as well as the UTC offset.
We will, use all of the above methods that are used to fetch current system’s date and time in an example to further elaborate the concept!

Have a look at our next example.

Example8

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
      static void Main()
        {
          Console.WriteLine("Fetching current date and time\n");
          Console.WriteLine("*************************");

          Console.WriteLine("\nCurrent Time.");
          Console.WriteLine(DateTime.Now);
          Console.WriteLine(DateTimeOffset.Now);

          Console.WriteLine("\ncurrent Date.");
          Console.WriteLine(DateTime.Today);

          Console.WriteLine("\nCurrent UTC time.");
          Console.WriteLine(DateTime.UtcNow);
          Console.WriteLine(DateTimeOffset.UtcNow);

          Console.ReadLine();
        }
    }
}

Here in this code, we have first displayed the current time with and without UTC offset using DateTime.Now and DateTimeOffset.Now structs. Next we have simple fetch the todays date using DateTime.Today, then we fetched the UTC time, not the time of the system. The UTC time is displayed with and without UTC offset using DateTime.UtcNow and DateTimeOffset.UtcNow. Have a look at the output and then I will explain how the compiler fetched these dates and time.

Output8

http://imgs.g4estatic.com/c-sharp/date-time/output8.png

Have a look at the output, here, first of all, we simply displayed the current time. In the next line, you would find that after the date ‘+05:00’ is appended. Since, the time zone of my machine is UTC +, therefore when I used DateTimeOffset.Now to display the current time, It also displayed the offset along with the time. Next we have simply displayed the current date on the screen. The last two lines of the output are particularly important. In these lines, we have first displayed the current time with respect to UTC time zone. This has been done using DateTime.UtcNow. The offset flag is not visible since we are using only the DateTime struct. In the next line, we have displayed the UTC time with offset which is 0 because the time is already in terms of UTC standard time. Another important thing to notice here is that you can see current time of the system us 4:16:12 and UTC time is 11:15:12 which shows that the current time is UTC +5.

Using DateTime and DateTimeOffset



You can also get the year, months, minutes from DateTime and DateTimeOffset structs. For instance if you only want to fetch year, you can do DateTime.Year. Similarly, for other parts of the DateTime you can call corresponding variables.

Another extremely important thing is that you can also add number of days, year, months and minutes etc. to a DateTimeStruct, for instance if you write DateTime.AddMonths(6), it will return a new DateTime struct where 6 months would have been added in the previous date. Also, you can subtract two dates, where the returning value is a TimeSpan. These concepts can be better understood when presented in the form of running example. Have a look at Example9.

Example9

Code:

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {
            DateTime date = new DateTime(2014, 3, 3, 6, 30, 14);

            Console.WriteLine("Year:" + date.Year);
            Console.WriteLine("Month:" + date.Month);
            Console.WriteLine("Day:" + date.Day);
            Console.WriteLine("Day of the week:" + date.DayOfWeek);
            Console.WriteLine("Day of the year:" + date.DayOfYear);
            Console.WriteLine("Hour:" + date.Hour);
            Console.WriteLine("Minute:" + date.Minute);
            Console.WriteLine("Seconds:" + date.Second);

            Console.WriteLine("\nAdding days, hours, minutes etc to a date");

            Console.WriteLine("Add 10 days");
            Console.WriteLine(date.AddDays(10));

            Console.WriteLine("\nAdd 2 years");
            Console.WriteLine(date.AddYears(2));

            Console.WriteLine("\nAdd 6 Months");
            Console.WriteLine(date.AddMonths(6));

            Console.WriteLine("\nSubtract 6 Months");
            Console.WriteLine(date.AddMonths(-6));

            Console.WriteLine("\nSubtracting two dates");
            Console.WriteLine(date.Subtract(new DateTime(2014,1,3)));

            Console.ReadLine();
        }
    }
}

We will explain the above code line by line. We simply declared a DateTime struct named date and initialized it with some values. Then, we displayed the year, month and day contained by the date using date.Year, date.Month and date.Day.

Next line is very interesting, we can also find out what is the day of the week on a particular day by calling DayOfWeek on a DateTime struct. Similarly, we can find out what is the day number out of 365 days of the year using DayOfYear. In the next two lines found these two values of the ‘date’ struct. Next, we found the hours, minutes and seconds portion of the date in a way similar to what we used for finding years, months and days.

After that we used some functions that are used for adding, years, months, days and minutes etc. to a date. We added 10 days to date using date.AddDays(10), 2 years using date.AddYears(2) and 6 months using date.AddMonths(6). We are displaying the value of date as soon as we make any change. What if we want to go to date 6 months before the date under consideration? The answer is very interesting, if you write a negative value in these add methods, for instance if your write date.AddMonths(-6), it will return a date of exactly 6 months ago.

Lastly, there is another extremely interesting thing to note. We have used date.Subtract() method which takes another DateTime struct as a variable and calculates the difference between two structs. By difference it means time span between two dates in days, followed by number of hours, minutes and seconds. The output of the code in Example9 is as follows.

Output9

http://imgs.g4estatic.com/c-sharp/date-time/output9.png

In Example9, while adding minutes and days we used AddMinutes and AddDays methods. We can also add a certain time span in an existing date using simple Add method of DateTime struct. Also, if we use ‘+’ operator between a DateTime and a TimeSpan struct, the result will be a new DateTime struct which contains the added sum. These two concepts are explained in the last example of this tutorial. Have a look at Example10.

Example10
Code:

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CSharpTutorial
{
    class Program
    {
        public static void Main()
        {

            DateTime date = new DateTime(2014, 3, 3, 6, 30, 14);

            TimeSpan time = TimeSpan.FromDays(10);

            Console.WriteLine(date.Add(time));

            Console.WriteLine(date + time);

            Console.ReadLine();
        }
    }
}

In this example we declared a ‘date’ struct of type DateTime and ‘time’ struct of type TimeSpan and then added them using Add static method of DateTime struct and then overloaded ‘+’ operator. You would find that the result of both expressions will be same as shown in the output of this code.

Output10

http://imgs.g4estatic.com/c-sharp/da...e/output10.png

Lastly, about leap years; Good news is that you don’t need to implement any explicit logic to handle the dates and times involving the leap years, like other countless built-in .NET capabilities, leap year scenarios are handled by .NET framework explicitly.


All times are GMT +5.5. The time now is 23:00.