Home > c# > Working with vague dates (90’s, Sept 2000 etc.)

Working with vague dates (90’s, Sept 2000 etc.)

December 16th, 2009 fbis Leave a comment Go to comments

On a recent project I had to allow users to upload their memories. Memories are vague things and I had to enable users to upload and assign incomplete dates. They needed to be able to enter ‘The 90’s’ or ‘September 2000′ as well as complete dates ‘1st Feb 2009′.

I could have separated all components and build the dates on each read but that would be very db intensive so I created a class that would remember the vague date but build a complete date for storage in the database so we could process them normally.

I created properties for the date components (day, month, year, era) and a normal date. When any of the d/m/y properties were set the class builds a random date based around the completed parts. So If you only supply a month and year the class generates a random day.

/// 
/// Type for the vague dates
/// 
/// A Vague date is a date that is not complete. Say January 2009, or in the 90's.
/// the unfilled date parts so /// that we still have a real date to order/filter by.
/// This class is used to support such dates and generate a random date to supply 
public class VagueDateType
{
	#region Constructors (3) 
 
    public VagueDateType(int day, int month, int year, int era)
    {
        Day = day;
        Month = month;
        Year = year;
        Era = era;
    }
 
    public VagueDateType(DateTime date) { Date = date;}
 
    public VagueDateType() { }
 
		#endregion Constructors 
 
		#region Properties (6) 
 
    public DateTime Date {get;set;}
 
    public int Day { get; set; }
 
    public int Era { get; set; }
    /// 
    /// Is the current data valid
    ///When Day, Month, Year, Era are all zero then we have a full date 
    ///and the VagueDateType.IsVagueDate returns false.
    /// If Day, Month, Year, Era are larger than zero then the 
    /// VagueDateType.IsVagueDate returns true.
    public bool IsValid
    {
        get
        {
            try { BuildDate(); }
            catch (Exception ex)
            {
                //failed due to incorrect date parts
                return false;
            }
            //we have a date
            if (Date != DateTime.MinValue) return true;
            //do we have valid date parts
            if (Era != 0 & Era> 1800 & Era < 2100) return true;
            if (Year != 0 & Month == 0 & Day == 0) return true;
            if (Year != 0 & Month != 0 & Day == 0) return true;
            if (Year != 0 & Month != 0 & Day != 0) return true;
            return false;
        }
    }
    public bool IsVagueDate
    {
        get
        {
            if (Day != 0 || Month != 0 || Year != 0 || Era != 0) { return true; } else { return false; }
        }
    }
 
    public int Month { get; set; }
 
    public int Year { get; set; }
 
	#endregion Properties 
 
	#region Methods (5) 
 
	// Public Methods (5) 
 
    public DateTime BuildDate()
    {
        //If we have a date return that else build a random one with the info we have
        if (Date == DateTime.MinValue)
        {
            DateTime d = DateTime.MinValue;
            int day = 0, month = 0, year = Year;
            Random Rnd = new Random();
 
            day = Day == 0 ? Rnd.Next(1, 28) : Day;
            month = Month == 0 ? Rnd.Next(1, 12) : Month;
 
            if (Year == 0)
            {
                //No year so must be an era
                year = Era + Rnd.Next(1, 9);
            }
            d = new DateTime(year, month, day);
            return d;
        }
        else
        {
            return Date;
        }
    }
    /// 
    /// Builds a date replacing 1st with any unsupplied value
    /// 
    ///
 
    /// The built date and an out param containg the next period
    public DateTime BuildDate(bool zeroUnsuppliedParts, out DateTime nextPeriod)
    {
        int day = 0, month = 0, year = Year;
        eDatePart largestPopulatedPart = eDatePart.None;
 
        if (Era != 0)
        {
            //No year so must be an era
            year = Era;
            largestPopulatedPart = eDatePart.Era;
        }
        if (Year == 0)
        {
            year = 1;
        }
        else
        {
            year = Year;
            largestPopulatedPart = eDatePart.Year;
        }
        if (Month == 0)
        {
            month = 1;
        }
        else
        {
            month = Month;
            largestPopulatedPart = eDatePart.Month;
        }
        if (Day == 0)
        {
            day = 1;
        }
        else
        {
            day = Day;
            largestPopulatedPart = eDatePart.Day;
        }
 
        DateTime d = new DateTime(year, month, day);
        nextPeriod = NextPeriod(largestPopulatedPart, d);
        return d;
    }
    /// 
    /// Which is the most detailed part of the vague date
    /// 
    /// 
    public eDatePart SmallestDatePart()
    {
        eDatePart largestPopulatedPart = eDatePart.None;
        if (Era != 0)
        {
            largestPopulatedPart = eDatePart.Era;
        }
        if (Year != 0)
        {
            largestPopulatedPart = eDatePart.Year;
        }
        if (Month != 0)
        {
            largestPopulatedPart = eDatePart.Month;
        }
        if (Day != 0)
        {
            largestPopulatedPart = eDatePart.Day;
        }
 
        return largestPopulatedPart;
    }
 
    public void Clear()
    {
        Day = 0;
        Month = 0;
        Year = 0;
        Era = 0;
        Date = new DateTime();
    }
 
    public void Populate(int day, int month, int year, int era)
    {
        Day = day;
        Month = month;
        Year = year;
        Era = era;
    }
 
    public void PopulateFromDate(DateTime date)
    {
        Date = date;
    }
    /// 
    /// ToString()
    /// 
    /// Returns the date formatted for use in rendering 
    /// 
    /// FullDate = "Monday, 13 Febuary 1987"
    /// Month/Year = "Febuary 1987"
    /// Year = "1987"
    /// Era = "1990-1999"
    /// 
    public override string ToString()
    {
        if (Date != DateTime.MinValue)
        {
            return Date.ToString("ddd, MMM dd yyyy");
        }
        else
        {
            //partial date so build it
            if(Day == 0 &amp; Month == 0 &amp; Year == 0 &amp; Era != 0){
                return Era.ToString() + "-" + (Era + 9).ToString();
                }
            if (Day == 0 &amp; Month == 0 &amp; Year != 0)
            {
                return Year.ToString();
            }
            if (Day == 0 &amp; Month != 0)
            {
                DateTime d = new DateTime(Year, Month, 1);
                return d.ToString("MMMM yyyy");
            }
        }
        return "";
    }
    public DateTime NextPeriod(eDatePart part, DateTime startDate)
    {
        switch (part)
        {
            case eDatePart.Day:
                return startDate.AddDays(1);
                break;
            case eDatePart.Month:
                return startDate.AddMonths(1);
                break;
            case eDatePart.Year:
                return startDate.AddYears(1);
                break;
            case eDatePart.Era:
                return startDate.AddYears(10);
                break;
            default:
                return new DateTime();
                break;
        }
    }
 
		#endregion Methods
    public enum eDatePart
    {
        None=0,
        Day = 1,
        Month = 2,
        Year = 3,
        Era = 4,
        All = 5
    }
}
Categories: c# Tags:
  1. No comments yet.
  1. No trackbacks yet.