/// <summary>Creates an <code>XMPDateTime</code>-instance from a calendar.</summary>
        /// <param name="calendar">a <code>Calendar</code></param>
        public XMPDateTimeImpl(Sharpen.Calendar calendar)
        {
            // EMPTY
            // extract the date and timezone from the calendar provided
            DateTime     date = calendar.GetTime();
            TimeZoneInfo zone = calendar.GetTimeZone();

            // put that date into a calendar the pretty much represents ISO8601
            // I use US because it is close to the "locale" for the ISO8601 spec
            Sharpen.GregorianCalendar intCalendar = (Sharpen.GregorianCalendar)Sharpen.Calendar.GetInstance(CultureInfo.InvariantCulture);
            intCalendar.SetGregorianChange(Sharpen.Extensions.CreateDate(long.MinValue));
            intCalendar.SetTimeZone(zone);
            intCalendar.SetTime(date);
            this.year  = intCalendar.Get(Sharpen.CalendarEnum.Year);
            this.month = intCalendar.Get(Sharpen.CalendarEnum.Month) + 1;
            // cal is from 0..12
            this.day         = intCalendar.Get(Sharpen.CalendarEnum.DayOfMonth);
            this.hour        = intCalendar.Get(Sharpen.CalendarEnum.HourOfDay);
            this.minute      = intCalendar.Get(Sharpen.CalendarEnum.Minute);
            this.second      = intCalendar.Get(Sharpen.CalendarEnum.Second);
            this.nanoSeconds = intCalendar.Get(Sharpen.CalendarEnum.Millisecond) * 1000000;
            this.timeZone    = intCalendar.GetTimeZone();
            // object contains all date components
            hasDate = hasTime = hasTimeZone = true;
        }
 /// <summary>
 /// Creates an <c>XMPDateTime</c>-instance from
 /// a <c>Date</c> and a <c>TimeZone</c>.
 /// </summary>
 /// <param name="date">a date describing an absolute point in time</param>
 /// <param name="timeZone">a TimeZone how to interpret the date</param>
 public XmpDateTime(DateTime date, TimeZoneInfo timeZone)
 {
     var calendar = new GregorianCalendar(timeZone);
     calendar.SetTime(date);
     _year = calendar.Get(CalendarEnum.Year);
     _month = calendar.Get(CalendarEnum.Month) + 1;
     // cal is from 0..12
     _day = calendar.Get(CalendarEnum.DayOfMonth);
     _hour = calendar.Get(CalendarEnum.HourOfDay);
     _minute = calendar.Get(CalendarEnum.Minute);
     _second = calendar.Get(CalendarEnum.Second);
     _nanoseconds = calendar.Get(CalendarEnum.Millisecond) * 1000000;
     _timeZone = timeZone;
     // object contains all date components
     HasDate = HasTime = HasTimeZone = true;
 }
 /// <summary>
 /// Creates an <code>XMPDateTime</code>-instance from
 /// a <code>Date</code> and a <code>TimeZone</code>.
 /// </summary>
 /// <param name="date">a date describing an absolute point in time</param>
 /// <param name="timeZone">a TimeZone how to interpret the date</param>
 public XMPDateTimeImpl(DateTime date, TimeZoneInfo timeZone)
 {
     Sharpen.GregorianCalendar calendar = new Sharpen.GregorianCalendar(timeZone);
     calendar.SetTime(date);
     this.year  = calendar.Get(Sharpen.CalendarEnum.Year);
     this.month = calendar.Get(Sharpen.CalendarEnum.Month) + 1;
     // cal is from 0..12
     this.day         = calendar.Get(Sharpen.CalendarEnum.DayOfMonth);
     this.hour        = calendar.Get(Sharpen.CalendarEnum.HourOfDay);
     this.minute      = calendar.Get(Sharpen.CalendarEnum.Minute);
     this.second      = calendar.Get(Sharpen.CalendarEnum.Second);
     this.nanoSeconds = calendar.Get(Sharpen.CalendarEnum.Millisecond) * 1000000;
     this.timeZone    = timeZone;
     // object contains all date components
     hasDate = hasTime = hasTimeZone = true;
 }
        /// <summary>
        /// Creates an <c>XMPDateTime</c>-instance from
        /// a <c>Date</c> and a <c>TimeZone</c>.
        /// </summary>
        /// <param name="date">a date describing an absolute point in time</param>
        /// <param name="timeZone">a TimeZone how to interpret the date</param>
        public XmpDateTime(DateTime date, TimeZoneInfo timeZone)
        {
            var calendar = new GregorianCalendar(timeZone);

            calendar.SetTime(date);
            _year  = calendar.Get(CalendarEnum.Year);
            _month = calendar.Get(CalendarEnum.Month) + 1;
            // cal is from 0..12
            _day         = calendar.Get(CalendarEnum.DayOfMonth);
            _hour        = calendar.Get(CalendarEnum.HourOfDay);
            _minute      = calendar.Get(CalendarEnum.Minute);
            _second      = calendar.Get(CalendarEnum.Second);
            _nanoseconds = calendar.Get(CalendarEnum.Millisecond) * 1000000;
            _timeZone    = timeZone;
            // object contains all date components
            HasDate = HasTime = HasTimeZone = true;
        }
		/// <summary>
		/// Creates an <code>XMPDateTime</code>-instance from
		/// a <code>Date</code> and a <code>TimeZone</code>.
		/// </summary>
		/// <param name="date">a date describing an absolute point in time</param>
		/// <param name="timeZone">a TimeZone how to interpret the date</param>
		public XMPDateTimeImpl(DateTime date, TimeZoneInfo timeZone)
		{
			Sharpen.GregorianCalendar calendar = new Sharpen.GregorianCalendar(timeZone);
			calendar.SetTime(date);
			this.year = calendar.Get(Sharpen.CalendarEnum.Year);
			this.month = calendar.Get(Sharpen.CalendarEnum.Month) + 1;
			// cal is from 0..12
			this.day = calendar.Get(Sharpen.CalendarEnum.DayOfMonth);
			this.hour = calendar.Get(Sharpen.CalendarEnum.HourOfDay);
			this.minute = calendar.Get(Sharpen.CalendarEnum.Minute);
			this.second = calendar.Get(Sharpen.CalendarEnum.Second);
			this.nanoSeconds = calendar.Get(Sharpen.CalendarEnum.Millisecond) * 1000000;
			this.timeZone = timeZone;
			// object contains all date components
			hasDate = hasTime = hasTimeZone = true;
		}
		public virtual void Now()
		{
			string dateStr = "2007-02-21 15:35:00 +0100";
			DateTime refDate = SystemReader.GetInstance().GetSimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"
				).Parse(dateStr);
			GregorianCalendar cal = new GregorianCalendar(SystemReader.GetInstance().GetTimeZone
				(), SystemReader.GetInstance().GetLocale());
			cal.SetTime(refDate);
			DateTime parse = GitDateParser.Parse("now", cal);
			NUnit.Framework.Assert.AreEqual(refDate, parse);
			long t1 = SystemReader.GetInstance().GetCurrentTime();
			parse = GitDateParser.Parse("now", null);
			long t2 = SystemReader.GetInstance().GetCurrentTime();
			NUnit.Framework.Assert.IsTrue(t2 >= parse.GetTime() && parse.GetTime() >= t1);
		}
		public virtual void DaysAndWeeksAgo()
		{
			string dateStr = "2007-02-21 15:35:00 +0100";
			SimpleDateFormat df = SystemReader.GetInstance().GetSimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"
				);
			DateTime refDate = df.Parse(dateStr);
			GregorianCalendar cal = new GregorianCalendar(SystemReader.GetInstance().GetTimeZone
				(), SystemReader.GetInstance().GetLocale());
			cal.SetTime(refDate);
			DateTime parse = GitDateParser.Parse("2 weeks ago", cal);
			NUnit.Framework.Assert.AreEqual(df.Parse("2007-02-07 15:35:00 +0100"), parse);
			parse = GitDateParser.Parse("3 days 2 weeks ago", cal);
			NUnit.Framework.Assert.AreEqual(df.Parse("2007-02-04 15:35:00 +0100"), parse);
			parse = GitDateParser.Parse("3.day.2.week.ago", cal);
			NUnit.Framework.Assert.AreEqual(df.Parse("2007-02-04 15:35:00 +0100"), parse);
		}