Still More Fun With DateTime

March 30th, 2009

DateTime is fun, really. You can get the difference between dates, get the first Sunday of some arbitrary year, or implement business logic to define a week of the year.


using System;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)  
        {  
            DateTime theDate = DateTime.Parse("03/12/2008"); 
            // the day of the week that was, as an integer (0-based)
            Console.WriteLine(String.Format("day of week, as integer, was {0}", (int)theDate.DayOfWeek));

            // the day of the week that was, as a string ("Wednesday")
            Console.WriteLine(String.Format("day of week, as integer, was {0}", theDate.DayOfWeek));  

            // first day of the week, Sunday, date 
            DateTime firstOfWeek = theDate.AddDays((int)DayOfWeek.Sunday - (int)theDate.DayOfWeek);
            Console.WriteLine(String.Format("first day of the week, Sunday, was {0}", firstOfWeek.ToShortDateString()));

            // first Sunday of the calendar year of that date
            DateTime firstOfYear = new DateTime(theDate.Year, 1, 1);
            DateTime firstSundayOfYear = firstOfYear.AddDays((int)DayOfWeek.Sunday - (int)firstOfYear.DayOfWeek);
            if (firstSundayOfYear < firstOfYear) firstSundayOfYear = firstSundayOfYear.AddDays(7);
            Console.WriteLine(String.Format("first sunday of year is/was {0}", firstSundayOfYear.ToShortDateString()));  

            // the week of the year that was, 1 - 52, as the difference between this last sunday and the first sunday of the year, in weeks
            // (your definition of "week of the year" may vary, this is not standardized)
            TimeSpan difference = firstOfWeek - firstSundayOfYear;
            int numWeeks = (int)difference.TotalDays / 7;
            Console.WriteLine(String.Format("week number is/was {0}", numWeeks.ToString()));  

            Console.Read();  
        }
    }
}

Related posts: 
C#.NET: 4 payroll/calendar date calculations
Fun with DateTime 

Did this help you? Please bookmark or share it! Did I mess up anywhere? Let me know in the comments.  =)

Storing different types in System.Array

March 21st, 2009

I came across a list of C# interview questions. One of them was asking if you could store multiple data types in System.Array. The answer given was “no”. However, that’s not entirely true.

You can indeed store pretty much anything you want if you declare an Array of type Object (or other shared base class). They will be stored as that base class, but their real type is maintained.

See sample code:


            object[] a = new object[10];
            int j = 1;
            a[0] = j;
            string s = "foo";
            a[1] = s;
            bool b = true;
            a[2] = b;
 
            for (int i = 0; i < a.Length; i++ )
            {
                object o = a[i];
                if (o != null) Console.WriteLine(o.GetType().ToString());
            }
          

Written to the console will be the actual types of the objects. You can use the “is” operator to check the type of the object before casting it or trying to use it.


            for (int i = 0; i < a.Length; i++ )
            {
                object o = a[i];
                if (o != null)
                {
                    if (o is string) Console.WriteLine(o);
                }
            }
You don’t have to use Object if the classes you are going to be storing share a parent class. Use whatever the first shared parent class happens to be. 

This technique has limited real-world application. If you need to do something like this, seriously think about your design and why you think you need it. Why do you need an Array, and why are you storing a bunch of different types in it? Here is an example, right from MSDN, where they are storing various Controls in an Array.

Was this interesting? Please share it! I need all the friends I can get.  =)

XML Serialization and List

January 25th, 2009

I was writing a small wrapper class to consume a third party XML response from a web service. Using a little helper class is a lot easier than playing with DOM. One of the elements was an Errors element that could have multiple Error child elements, like so:


<Errors>
   <Error>detail</Error>
   <Error>detail</Error>
</Errors>

In my class, I wanted to use a List<string> to account for this, but since I was consuming XML, I needed to be able to tell it the element name, otherwise it serializes and deserializes as just “string”, like this.


<?xml version="1.0" encoding="utf-16"?>
<WebServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<statusCode>failure</statusCode>
<recordsAffected>0</recordsAffected>
<Errors>
   <string>Foo</string>
</Errors>
</WebServiceResponse>

 

So when I tried to read in the xml, I got an error because it couldn’t find an Error element (it was string). Not so helpful.

I needed the ElementName property in my class.

[XmlArrayItem(typeof(string), ElementName = "Error")]
public List<string> Errors;

Adding this, the element was correctly deserialized so it could read something like this.


<?xml version="1.0" encoding="utf-16"?>
<WebServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<statusCode>failure</statusCode>
<recordsAffected>0</recordsAffected>
<Errors>
   <Error>Foo</Error>
</Errors>
</WebServiceResponse>

Here is some code to play with so you can try it out and see how the attribute affects serialization and deserialization. Have fun!


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

namespace ConsoleApplication1
{
    public class Program
    {
        public class WebServiceResponse
        {
            public string statusCode;
            public string recordsAffected;

            [XmlArrayItem(typeof(string), ElementName = "Error")]
            public List<string> Errors;
        }

        static void Main(string[] args)
        {
            // if we were to set the elements themselves, it could look like this
            WebServiceResponse r = new WebServiceResponse();
            r.statusCode = "success";
            r.recordsAffected = "1";
            r.Errors = new List<string>();
            r.Errors.Add("Foo");

            XmlSerializer serializer = new XmlSerializer(typeof(WebServiceResponse));
            StringBuilder sb = new StringBuilder();
            serializer.Serialize(new StringWriter(sb), r);
            Console.WriteLine(sb.ToString());

            string s = sb.ToString();
            // more likely, we'd be reading them in from an XML response to manipulate, like so
            // (you'd have the xml response from a web service in a string or such)
            TextReader sr = new StringReader(s);
            WebServiceResponse r2 = serializer.Deserialize(sr) as WebServiceResponse;
            int numErrors = r2.Errors == null ? 0 : r2.Errors.Count;
            Console.WriteLine("There were " + numErrors + " errors");

            Console.Read();
        }
    }
}

Using Type.Missing for optional parameters

January 8th, 2009

If you read my posts much, you’ll notice I focus on C# a lot. I’m not a big VB.NET fan. One thing VB.NET has that C# doesn’t have (yet — I hear they’re adding it in C# 4) though is optional parameters.

.NET, of course, allows you to mix and match languages. I can use a 3rd party library, or an in-house library, that was created with VB.NET, even though I code in C#. Not a problem there; they play nicely together.

A problem did arise, however, when many of the methods I was calling had optional parameters. C# was making me pass an object, and I didn’t know I had a choice. I created dummy objects and overloaded methods to get what I needed. That was a mistake.

I wish I had known then about Type.Missing. I found about it when I was playing with COM and studying for a certification test. COM also has optional parameters. The example I was reading used Type.Missing, and I wanted to cry. I had spent way too much time smashing my head into my desk with the library fiasco. All I needed was this simple construct.

So I’m sharing it here, in case anyone else has overlooked this. Maybe I’ll save someone a headache. Or a splintered desk.

Here is a simple example of using Type.Missing with Excel COM interop.

Note that you must add references to your project to Excel (Excel Object Library or similar, assuming you have Excel installed on your computer) from the COM tab in order for it to work. Adding a reference to that will also add one for Microsoft.Office.Core for you. You must also set Excel to allow code to automate it.

using System;
using System.Runtime.InteropServices;
using Excel;
namespace ConsoleApplication1
{
   class Program
   {
   private static Object OptionalParamHandler = Type.Missing;
   static void Main(string[] args)
   {
      try
      {
         Application NewExcelApp = new Application();
         NewExcelApp.Visible = true;
         NewExcelApp.Workbooks.Add(Type.Missing);
         NewExcelApp.Worksheets.Add(OptionalParamHandler,
         OptionalParamHandler, OptionalParamHandler,
         OptionalParamHandler);
      }   
      catch (Exception e)
      {
         Console.WriteLine("Exception: " + e.Message + " " + e.StackTrace);
      }
      Console.ReadLine();
   }
}
}

Fun with DateTime

November 17th, 2008

The results of my messing around with .NET DateTime. Hope this is useful for someone else!


using System;
namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
      // fun with DateTime
      // right now, including the time
      Console.WriteLine(DateTime.Now);
 
      // today's date, no time (midnite)
      Console.WriteLine(DateTime.Today);

      // stripping a time off a DateTime (so it's midnite, useful for database queries)
      DateTime startDate = DateTime.Parse("10/31/2008 5:25 pm"); // pretend this came from a database or something
      Console.WriteLine(startDate); // see the time displayed
      startDate = startDate.Date; // this is just the date portion with no time
      Console.WriteLine(startDate); // see, just has the date now

      // difference, in number of days, between two dates, human-logic, that is, the 5th is 2 days after the 3rd, no matter what time it was
      DateTime endDate = DateTime.Parse("11/03/2008 4:25 pm"); // pretend this came from a database or something, too
      int days = (startDate.Date - endDate.Date).Duration().Days; // absolute value, order of start and end dates is not important
      Console.WriteLine(days);
     int days2 = (startDate.Date - endDate.Date).Days; // real value, order of start and end dates IS important
      Console.WriteLine(days2);

      // difference between dates with time portion, such as .25 hours (time and attendance, payroll)
      startDate = DateTime.Parse("11/17/2008 8:00 am");
      endDate = DateTime.Parse("11/17/2008 4:45 pm");
      TimeSpan interval = endDate - startDate; // order matters
      Console.WriteLine(interval);
 
      // hey, don't we get a lunch break?
      DateTime startLunch = DateTime.Parse("11/17/2008 12:00 pm");
      DateTime endLunch = DateTime.Parse("11/17/2008 12:25 pm");
      TimeSpan lunchInterval = endLunch - startLunch; 
      Console.WriteLine(interval - lunchInterval); // 20 minutes of overtime! (yeah, right)

      Console.Read();
      }
   }
}