/// <summary> /// Make sure a time is UTC. If the time zone is not UTC, the time is /// adjusted and the time zone set to be UTC. /// </summary> /// <param name="dateTime"> /// the <code>XMPDateTime</code> variable containing the time to /// be modified. </param> /// <returns> Returns an updated <code>XMPDateTime</code>-object. </returns> public static IXmpDateTime ConvertToUtcTime(IXmpDateTime dateTime) { long timeInMillis = dateTime.Calendar.TimeInMillis; XmpCalendar cal = new XmpCalendar(); cal.TimeInMillis = timeInMillis; return new XmpDateTimeImpl(cal); }
/// <param name="iso8601String"> a date string that is ISO 8601 conform. </param> /// <param name="binValue"> an existing XMPDateTime to set with the parsed date </param> /// <returns> Returns an XMPDateTime-object containing the ISO8601-date. </returns> /// <exception cref="XmpException"> Is thrown when the string is non-conform. </exception> public static IXmpDateTime Parse(string iso8601String, IXmpDateTime binValue) { if (iso8601String == null) { throw new XmpException("Parameter must not be null", XmpError.BADPARAM); } if (iso8601String.Length == 0) { return binValue; } ParseState input = new ParseState(iso8601String); if (input.Ch(0) == '-') { input.Skip(); } // Extract the year. int value = input.GatherInt("Invalid year in date string", 9999); if (input.HasNext() && input.Ch() != '-') { throw new XmpException("Invalid date string, after year", XmpError.BADVALUE); } if (input.Ch(0) == '-') { value = -value; } binValue.Year = value; if (!input.HasNext()) { return binValue; } input.Skip(); // Extract the month. value = input.GatherInt("Invalid month in date string", 12); if (input.HasNext() && input.Ch() != '-') { throw new XmpException("Invalid date string, after month", XmpError.BADVALUE); } binValue.Month = value; if (!input.HasNext()) { return binValue; } input.Skip(); // Extract the day. value = input.GatherInt("Invalid day in date string", 31); if (input.HasNext() && input.Ch() != 'T') { throw new XmpException("Invalid date string, after day", XmpError.BADVALUE); } binValue.Day = value; if (!input.HasNext()) { return binValue; } input.Skip(); // Extract the hour. value = input.GatherInt("Invalid hour in date string", 23); binValue.Hour = value; if (!input.HasNext()) { return binValue; } // Extract the minute. if (input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid minute in date string", 59); if (input.HasNext() && input.Ch() != ':' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after minute", XmpError.BADVALUE); } binValue.Minute = value; } if (!input.HasNext()) { return binValue; } if (input.HasNext() && input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid whole seconds in date string", 59); if (input.HasNext() && input.Ch() != '.' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after whole seconds", XmpError.BADVALUE); } binValue.Second = value; if (input.Ch() == '.') { input.Skip(); int digits = input.Pos(); value = input.GatherInt("Invalid fractional seconds in date string", 999999999); if (input.HasNext() && (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-')) { throw new XmpException("Invalid date string, after fractional second", XmpError.BADVALUE); } digits = input.Pos() - digits; for (; digits > 9; --digits) { value = value/10; } for (; digits < 9; ++digits) { value = value*10; } binValue.NanoSecond = value; } } else if (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after time", XmpError.BADVALUE); } if (!input.HasNext()) { // no Timezone at all return binValue; } if (input.Ch() == 'Z') { input.Skip(); } else if (input.HasNext()) { if (input.Ch() == '+') { } else if (input.Ch() == '-') { } else { throw new XmpException("Time zone must begin with 'Z', '+', or '-'", XmpError.BADVALUE); } input.Skip(); // Extract the time zone hour. if (input.HasNext()) { if (input.Ch() == ':') { input.Skip(); } else { throw new XmpException("Invalid date string, after time zone hour", XmpError.BADVALUE); } } } // create a corresponding TZ and set it time zone binValue.TimeZone = TimeZone.CurrentTimeZone; if (input.HasNext()) { throw new XmpException("Invalid date string, extra chars at end", XmpError.BADVALUE); } return binValue; }
/// <summary> /// Sets the local time zone without touching any other Any existing time zone value is replaced, /// the other date/time fields are not adjusted in any way. /// </summary> /// <param name="dateTime"> the <code>XMPDateTime</code> variable containing the value to be modified. </param> /// <returns> Returns an updated <code>XMPDateTime</code>-object. </returns> public static IXmpDateTime SetLocalTimeZone(IXmpDateTime dateTime) { XmpCalendar cal = dateTime.Calendar; cal.TimeZone = TimeZone.CurrentTimeZone; return new XmpDateTimeImpl(cal); }
/// <param name="iso8601String">a date string that is ISO 8601 conform.</param> /// <param name="binValue">an existing XMPDateTime to set with the parsed date</param> /// <returns>Returns an XMPDateTime-object containing the ISO8601-date.</returns> /// <exception cref="XmpException">Is thrown when the string is non-conform.</exception> public static IXmpDateTime Parse(string iso8601String, IXmpDateTime binValue) { if (iso8601String == null) { throw new XmpException("Parameter must not be null", XmpErrorCode.BadParam); } if (iso8601String.Length == 0) { return binValue; } var input = new ParseState(iso8601String); if (input.Ch(0) == '-') { input.Skip(); } // Extract the year. var value = input.GatherInt("Invalid year in date string", 9999); if (input.HasNext && input.Ch() != '-') { throw new XmpException("Invalid date string, after year", XmpErrorCode.BadValue); } if (input.Ch(0) == '-') { value = -value; } binValue.Year = value; if (!input.HasNext) { return binValue; } input.Skip(); // Extract the month. value = input.GatherInt("Invalid month in date string", 12); if (input.HasNext && input.Ch() != '-') { throw new XmpException("Invalid date string, after month", XmpErrorCode.BadValue); } binValue.Month = value; if (!input.HasNext) { return binValue; } input.Skip(); // Extract the day. value = input.GatherInt("Invalid day in date string", 31); if (input.HasNext && input.Ch() != 'T') { throw new XmpException("Invalid date string, after day", XmpErrorCode.BadValue); } binValue.Day = value; if (!input.HasNext) { return binValue; } input.Skip(); // Extract the hour. value = input.GatherInt("Invalid hour in date string", 23); binValue.Hour = value; if (!input.HasNext) { return binValue; } // Extract the minute. if (input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid minute in date string", 59); if (input.HasNext && input.Ch() != ':' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after minute", XmpErrorCode.BadValue); } binValue.Minute = value; } if (!input.HasNext) { return binValue; } if (input.HasNext && input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid whole seconds in date string", 59); if (input.HasNext && input.Ch() != '.' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after whole seconds", XmpErrorCode.BadValue); } binValue.Second = value; if (input.Ch() == '.') { input.Skip(); var digits = input.Pos(); value = input.GatherInt("Invalid fractional seconds in date string", 999999999); if (input.HasNext && (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-')) { throw new XmpException("Invalid date string, after fractional second", XmpErrorCode.BadValue); } digits = input.Pos() - digits; for (; digits > 9; --digits) { value = value / 10; } for (; digits < 9; ++digits) { value = value * 10; } binValue.Nanosecond = value; } } else { if (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after time", XmpErrorCode.BadValue); } } var tzSign = 0; var tzHour = 0; var tzMinute = 0; if (!input.HasNext) { // no Timezone at all return binValue; } if (input.Ch() == 'Z') { input.Skip(); } else { if (input.HasNext) { if (input.Ch() == '+') { tzSign = 1; } else { if (input.Ch() == '-') { tzSign = -1; } else { throw new XmpException("Time zone must begin with 'Z', '+', or '-'", XmpErrorCode.BadValue); } } input.Skip(); // Extract the time zone hour. tzHour = input.GatherInt("Invalid time zone hour in date string", 23); if (input.HasNext) { if (input.Ch() == ':') { input.Skip(); // Extract the time zone minute. tzMinute = input.GatherInt("Invalid time zone minute in date string", 59); } else { throw new XmpException("Invalid date string, after time zone hour", XmpErrorCode.BadValue); } } } } // create a corresponding TZ and set it time zone var offset = (TimeSpan.FromHours(tzHour) + TimeSpan.FromMinutes(tzMinute)); if (tzSign < 0) offset = -offset; #if PORTABLE binValue.TimeZone = TimeZoneInfo.Local; binValue.Offset = offset; #else binValue.TimeZone = TimeZoneInfo.CreateCustomTimeZone("OFFSET" + offset, offset, string.Empty, string.Empty); #endif if (input.HasNext) throw new XmpException("Invalid date string, extra chars at end", XmpErrorCode.BadValue); return binValue; }
/// <summary> /// Converts a <code>Calendar</code> into an ISO 8601 string. /// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: /// <ul> /// <li>YYYY /// <li>YYYY-MM /// <li>YYYY-MM-DD /// <li>YYYY-MM-DDThh:mmTZD /// <li>YYYY-MM-DDThh:mm:ssTZD /// <li>YYYY-MM-DDThh:mm:ss.sTZD /// </ul> /// /// Data fields: /// <ul> /// <li>YYYY = four-digit year /// <li>MM = two-digit month (01=January, etc.) /// <li>DD = two-digit day of month (01 through 31) /// <li>hh = two digits of hour (00 through 23) /// <li>mm = two digits of minute (00 through 59) /// <li>ss = two digits of second (00 through 59) /// <li>s = one or more digits representing a decimal fraction of a second /// <li>TZD = time zone designator (Z or +hh:mm or -hh:mm) /// </ul> /// <p> /// <em>Note:</em> ISO 8601 does not seem to allow years less than 1000 or greater than 9999. /// We allow any year, even negative ones. The year is formatted as "%.4d".<p> /// <em>Note:</em> Fix for bug 1269463 (silently fix out of range values) included in parsing. /// The quasi-bogus "time only" values from Photoshop CS are not supported. /// </summary> /// <param name="dateTime"> an XMPDateTime-object. </param> /// <returns> Returns an ISO 8601 string. </returns> public static string Render(IXmpDateTime dateTime) { return dateTime.Calendar.DateTime.ToString("s"); }
/// <seealso cref= XMPMeta#SetPropertyDate(String, String, XMPDateTime, /// PropertyOptions) </seealso> public virtual void SetPropertyDate(string schemaNs, string propName, IXmpDateTime propValue, PropertyOptions options) { SetProperty(schemaNs, propName, propValue, options); }
/// <summary>Converts a <c>Calendar</c> into an ISO 8601 string.</summary> /// <remarks> /// Converts a <c>Calendar</c> into an ISO 8601 string. /// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: /// <list type="bullet"> /// <item>YYYY</item> /// <item>YYYY-MM</item> /// <item>YYYY-MM-DD</item> /// <item>YYYY-MM-DDThh:mmTZD</item> /// <item>YYYY-MM-DDThh:mm:ssTZD</item> /// <item>YYYY-MM-DDThh:mm:ss.sTZD</item> /// </list> /// Data fields: /// <list type="bullet"> /// <item>YYYY = four-digit year</item> /// <item>MM = two-digit month (01=January, etc.)</item> /// <item>DD = two-digit day of month (01 through 31)</item> /// <item>hh = two digits of hour (00 through 23)</item> /// <item>mm = two digits of minute (00 through 59)</item> /// <item>ss = two digits of second (00 through 59)</item> /// <item>s = one or more digits representing a decimal fraction of a second</item> /// <item>TZD = time zone designator (Z or +hh:mm or -hh:mm)</item> /// </list> /// <para /> /// <em>Note:</em> ISO 8601 does not seem to allow years less than 1000 or greater than 9999. /// We allow any year, even negative ones. The year is formatted as "%.4d". /// <para /> /// <em>Note:</em> Fix for bug 1269463 (silently fix out of range values) included in parsing. /// The quasi-bogus "time only" values from Photoshop CS are not supported. /// </remarks> /// <param name="dateTime">an XMPDateTime-object.</param> /// <returns>Returns an ISO 8601 string.</returns> public static string Render(IXmpDateTime dateTime) { var buffer = new StringBuilder(); if (dateTime.HasDate) { // year is rendered in any case, even 0000 buffer.Append(dateTime.Year.ToString("0000")); if (dateTime.Month == 0) { return(buffer.ToString()); } // month buffer.Append('-'); buffer.Append(dateTime.Month.ToString("00")); if (dateTime.Day == 0) { return(buffer.ToString()); } // day buffer.Append('-'); buffer.Append(dateTime.Day.ToString("00")); // time, rendered if any time field is not zero if (dateTime.HasTime) { // hours and minutes buffer.Append('T'); buffer.Append(dateTime.Hour.ToString("00")); buffer.Append(':'); buffer.Append(dateTime.Minute.ToString("00")); // seconds and nanoseconds if (dateTime.Second != 0 || dateTime.Nanosecond != 0) { buffer.Append(':'); var seconds = dateTime.Second + dateTime.Nanosecond / 1e9d; buffer.AppendFormat("{0:00.#########}", seconds); } // time zone if (dateTime.HasTimeZone) { // used to calculate the time zone offset incl. Daylight Savings var timeInMillis = dateTime.Calendar.GetTimeInMillis(); var offset = (int)dateTime.TimeZone.GetUtcOffset(XmpDateTime.UnixTimeToDateTimeOffset(timeInMillis).DateTime).TotalMilliseconds; if (offset == 0) { // UTC buffer.Append('Z'); } else { var thours = offset / 3600000; var tminutes = Math.Abs(offset % 3600000 / 60000); buffer.Append(thours.ToString("+00;-00")); buffer.Append(tminutes.ToString(":00")); } } } } return(buffer.ToString()); }
/// <summary> /// Sets the local time zone without touching any other Any existing time zone value is replaced, /// the other date/time fields are not adjusted in any way. /// </summary> /// <param name="dateTime">the <c>XMPDateTime</c> variable containing the value to be modified.</param> /// <returns>Returns an updated <c>XMPDateTime</c>-object.</returns> public static IXmpDateTime SetLocalTimeZone(IXmpDateTime dateTime) { var cal = dateTime.Calendar; cal.SetTimeZone(TimeZoneInfo.Local); return new XmpDateTime(cal); }
/// <summary>Make sure a time is UTC.</summary> /// <remarks> /// Make sure a time is UTC. If the time zone is not UTC, the time is /// adjusted and the time zone set to be UTC. /// </remarks> /// <param name="dateTime"> /// the <c>XMPDateTime</c> variable containing the time to /// be modified. /// </param> /// <returns>Returns an updated <c>XMPDateTime</c>-object.</returns> public static IXmpDateTime ConvertToUtcTime(IXmpDateTime dateTime) { var timeInMillis = dateTime.Calendar.GetTimeInMillis(); var cal = new GregorianCalendar(TimeZoneInfo.Utc); cal.SetGregorianChange(XmpDateTime.UnixTimeToDateTime(long.MinValue)); cal.SetTimeInMillis(timeInMillis); return new XmpDateTime(cal); }
/// <exception cref="XmpException" /> public void SetPropertyDate(string schemaNs, string propName, IXmpDateTime propValue, PropertyOptions options) { SetProperty(schemaNs, propName, propValue, options); }
/// <exception cref="XmpException" /> public void SetPropertyDate(string schemaNs, string propName, IXmpDateTime propValue) { SetProperty(schemaNs, propName, propValue, null); }
/// <param name="iso8601String"> a date string that is ISO 8601 conform. </param> /// <param name="binValue"> an existing XMPDateTime to set with the parsed date </param> /// <returns> Returns an XMPDateTime-object containing the ISO8601-date. </returns> /// <exception cref="XmpException"> Is thrown when the string is non-conform. </exception> public static IXmpDateTime Parse(string iso8601String, IXmpDateTime binValue) { if (iso8601String == null) { throw new XmpException("Parameter must not be null", XmpError.BADPARAM); } if (iso8601String.Length == 0) { return(binValue); } ParseState input = new ParseState(iso8601String); if (input.Ch(0) == '-') { input.Skip(); } // Extract the year. int value = input.GatherInt("Invalid year in date string", 9999); if (input.HasNext() && input.Ch() != '-') { throw new XmpException("Invalid date string, after year", XmpError.BADVALUE); } if (input.Ch(0) == '-') { value = -value; } binValue.Year = value; if (!input.HasNext()) { return(binValue); } input.Skip(); // Extract the month. value = input.GatherInt("Invalid month in date string", 12); if (input.HasNext() && input.Ch() != '-') { throw new XmpException("Invalid date string, after month", XmpError.BADVALUE); } binValue.Month = value; if (!input.HasNext()) { return(binValue); } input.Skip(); // Extract the day. value = input.GatherInt("Invalid day in date string", 31); if (input.HasNext() && input.Ch() != 'T') { throw new XmpException("Invalid date string, after day", XmpError.BADVALUE); } binValue.Day = value; if (!input.HasNext()) { return(binValue); } input.Skip(); // Extract the hour. value = input.GatherInt("Invalid hour in date string", 23); binValue.Hour = value; if (!input.HasNext()) { return(binValue); } // Extract the minute. if (input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid minute in date string", 59); if (input.HasNext() && input.Ch() != ':' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after minute", XmpError.BADVALUE); } binValue.Minute = value; } if (!input.HasNext()) { return(binValue); } if (input.HasNext() && input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid whole seconds in date string", 59); if (input.HasNext() && input.Ch() != '.' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after whole seconds", XmpError.BADVALUE); } binValue.Second = value; if (input.Ch() == '.') { input.Skip(); int digits = input.Pos(); value = input.GatherInt("Invalid fractional seconds in date string", 999999999); if (input.HasNext() && (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-')) { throw new XmpException("Invalid date string, after fractional second", XmpError.BADVALUE); } digits = input.Pos() - digits; for (; digits > 9; --digits) { value = value / 10; } for (; digits < 9; ++digits) { value = value * 10; } binValue.NanoSecond = value; } } else if (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after time", XmpError.BADVALUE); } if (!input.HasNext()) { // no Timezone at all return(binValue); } if (input.Ch() == 'Z') { input.Skip(); } else if (input.HasNext()) { if (input.Ch() == '+') { } else if (input.Ch() == '-') { } else { throw new XmpException("Time zone must begin with 'Z', '+', or '-'", XmpError.BADVALUE); } input.Skip(); // Extract the time zone hour. if (input.HasNext()) { if (input.Ch() == ':') { input.Skip(); } else { throw new XmpException("Invalid date string, after time zone hour", XmpError.BADVALUE); } } } // create a corresponding TZ and set it time zone binValue.TimeZone = TimeZone.CurrentTimeZone; if (input.HasNext()) { throw new XmpException("Invalid date string, extra chars at end", XmpError.BADVALUE); } return(binValue); }
/// <summary> /// Converts a <code>Calendar</code> into an ISO 8601 string. /// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: /// <ul> /// <li>YYYY /// <li>YYYY-MM /// <li>YYYY-MM-DD /// <li>YYYY-MM-DDThh:mmTZD /// <li>YYYY-MM-DDThh:mm:ssTZD /// <li>YYYY-MM-DDThh:mm:ss.sTZD /// </ul> /// /// Data fields: /// <ul> /// <li>YYYY = four-digit year /// <li>MM = two-digit month (01=January, etc.) /// <li>DD = two-digit day of month (01 through 31) /// <li>hh = two digits of hour (00 through 23) /// <li>mm = two digits of minute (00 through 59) /// <li>ss = two digits of second (00 through 59) /// <li>s = one or more digits representing a decimal fraction of a second /// <li>TZD = time zone designator (Z or +hh:mm or -hh:mm) /// </ul> /// <p> /// <em>Note:</em> ISO 8601 does not seem to allow years less than 1000 or greater than 9999. /// We allow any year, even negative ones. The year is formatted as "%.4d".<p> /// <em>Note:</em> Fix for bug 1269463 (silently fix out of range values) included in parsing. /// The quasi-bogus "time only" values from Photoshop CS are not supported. /// </summary> /// <param name="dateTime"> an XMPDateTime-object. </param> /// <returns> Returns an ISO 8601 string. </returns> public static string Render(IXmpDateTime dateTime) { return(dateTime.Calendar.DateTime.ToString("s")); }
/// <param name="iso8601String">a date string that is ISO 8601 conform.</param> /// <param name="binValue">an existing XMPDateTime to set with the parsed date</param> /// <returns>Returns an XMPDateTime-object containing the ISO8601-date.</returns> /// <exception cref="XmpException">Is thrown when the string is non-conform.</exception> public static IXmpDateTime Parse(string iso8601String, IXmpDateTime binValue) { if (iso8601String == null) { throw new XmpException("Parameter must not be null", XmpErrorCode.BadParam); } if (iso8601String.Length == 0) { return(binValue); } var input = new ParseState(iso8601String); if (input.Ch(0) == '-') { input.Skip(); } // Extract the year. var value = input.GatherInt("Invalid year in date string", 9999); if (input.HasNext && input.Ch() != '-') { throw new XmpException("Invalid date string, after year", XmpErrorCode.BadValue); } if (input.Ch(0) == '-') { value = -value; } binValue.Year = value; if (!input.HasNext) { return(binValue); } input.Skip(); // Extract the month. value = input.GatherInt("Invalid month in date string", 12); if (input.HasNext && input.Ch() != '-') { throw new XmpException("Invalid date string, after month", XmpErrorCode.BadValue); } binValue.Month = value; if (!input.HasNext) { return(binValue); } input.Skip(); // Extract the day. value = input.GatherInt("Invalid day in date string", 31); if (input.HasNext && input.Ch() != 'T') { throw new XmpException("Invalid date string, after day", XmpErrorCode.BadValue); } binValue.Day = value; if (!input.HasNext) { return(binValue); } input.Skip(); // Extract the hour. value = input.GatherInt("Invalid hour in date string", 23); binValue.Hour = value; if (!input.HasNext) { return(binValue); } // Extract the minute. if (input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid minute in date string", 59); if (input.HasNext && input.Ch() != ':' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after minute", XmpErrorCode.BadValue); } binValue.Minute = value; } if (!input.HasNext) { return(binValue); } if (input.HasNext && input.Ch() == ':') { input.Skip(); value = input.GatherInt("Invalid whole seconds in date string", 59); if (input.HasNext && input.Ch() != '.' && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after whole seconds", XmpErrorCode.BadValue); } binValue.Second = value; if (input.Ch() == '.') { input.Skip(); var digits = input.Pos(); value = input.GatherInt("Invalid fractional seconds in date string", 999999999); if (input.HasNext && input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after fractional second", XmpErrorCode.BadValue); } digits = input.Pos() - digits; for (; digits > 9; --digits) { value = value / 10; } for (; digits < 9; ++digits) { value = value * 10; } binValue.Nanosecond = value; } } else if (input.Ch() != 'Z' && input.Ch() != '+' && input.Ch() != '-') { throw new XmpException("Invalid date string, after time", XmpErrorCode.BadValue); } var tzSign = 0; var tzHour = 0; var tzMinute = 0; if (!input.HasNext) { // no Timezone at all return(binValue); } if (input.Ch() == 'Z') { input.Skip(); } else if (input.HasNext) { switch (input.Ch()) { case '+': tzSign = 1; break; case '-': tzSign = -1; break; default: throw new XmpException("Time zone must begin with 'Z', '+', or '-'", XmpErrorCode.BadValue); } input.Skip(); // Extract the time zone hour. tzHour = input.GatherInt("Invalid time zone hour in date string", 23); if (input.HasNext) { if (input.Ch() == ':') { input.Skip(); // Extract the time zone minute. tzMinute = input.GatherInt("Invalid time zone minute in date string", 59); } else { throw new XmpException("Invalid date string, after time zone hour", XmpErrorCode.BadValue); } } } // create a corresponding TZ and set it time zone var offset = TimeSpan.FromHours(tzHour) + TimeSpan.FromMinutes(tzMinute); if (tzSign < 0) { offset = -offset; } binValue.TimeZone = TimeZoneInfo.Local; binValue.Offset = offset; if (input.HasNext) { throw new XmpException("Invalid date string, extra chars at end", XmpErrorCode.BadValue); } return(binValue); }
/// <summary> /// Make sure a time is local. If the time zone is not the local zone, the time is adjusted and /// the time zone set to be local. /// </summary> /// <param name="dateTime"> the <code>XMPDateTime</code> variable containing the time to be modified. </param> /// <returns> Returns an updated <code>XMPDateTime</code>-object. </returns> public static IXmpDateTime ConvertToLocalTime(IXmpDateTime dateTime) { long timeInMillis = dateTime.Calendar.TimeInMillis; // has automatically local timezone XmpCalendar cal = new XmpCalendar(); cal.TimeInMillis = timeInMillis; return new XmpDateTimeImpl(cal); }
/// <summary>Make sure a time is local.</summary> /// <remarks> /// Make sure a time is local. If the time zone is not the local zone, the time is adjusted and /// the time zone set to be local. /// </remarks> /// <param name="dateTime">the <c>XMPDateTime</c> variable containing the time to be modified.</param> /// <returns>Returns an updated <c>XMPDateTime</c>-object.</returns> public static IXmpDateTime ConvertToLocalTime(IXmpDateTime dateTime) { var timeInMillis = dateTime.Calendar.GetTimeInMillis(); // has automatically local timezone var cal = new GregorianCalendar(); cal.SetTimeInMillis(timeInMillis); return new XmpDateTime(cal); }
/// <summary>Convert from <c>XMPDateTime</c> to string.</summary> /// <param name="value">an <c>XMPDateTime</c></param> /// <returns>The string representation of the long.</returns> public static string ConvertFromDate(IXmpDateTime value) { return Iso8601Converter.Render(value); }
/// <summary>Converts a <c>Calendar</c> into an ISO 8601 string.</summary> /// <remarks> /// Converts a <c>Calendar</c> into an ISO 8601 string. /// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: /// <list type="bullet"> /// <item>YYYY</item> /// <item>YYYY-MM</item> /// <item>YYYY-MM-DD</item> /// <item>YYYY-MM-DDThh:mmTZD</item> /// <item>YYYY-MM-DDThh:mm:ssTZD</item> /// <item>YYYY-MM-DDThh:mm:ss.sTZD</item> /// </list> /// Data fields: /// <list type="bullet"> /// <item>YYYY = four-digit year</item> /// <item>MM = two-digit month (01=January, etc.)</item> /// <item>DD = two-digit day of month (01 through 31)</item> /// <item>hh = two digits of hour (00 through 23)</item> /// <item>mm = two digits of minute (00 through 59)</item> /// <item>ss = two digits of second (00 through 59)</item> /// <item>s = one or more digits representing a decimal fraction of a second</item> /// <item>TZD = time zone designator (Z or +hh:mm or -hh:mm)</item> /// </list> /// <para /> /// <em>Note:</em> ISO 8601 does not seem to allow years less than 1000 or greater than 9999. /// We allow any year, even negative ones. The year is formatted as "%.4d". /// <para /> /// <em>Note:</em> Fix for bug 1269463 (silently fix out of range values) included in parsing. /// The quasi-bogus "time only" values from Photoshop CS are not supported. /// </remarks> /// <param name="dateTime">an XMPDateTime-object.</param> /// <returns>Returns an ISO 8601 string.</returns> public static string Render(IXmpDateTime dateTime) { var buffer = new StringBuilder(); if (dateTime.HasDate) { // year is rendered in any case, even 0000 buffer.Append(dateTime.Year.ToString("0000")); if (dateTime.Month == 0) return buffer.ToString(); // month buffer.Append('-'); buffer.Append(dateTime.Month.ToString("00")); if (dateTime.Day == 0) return buffer.ToString(); // day buffer.Append('-'); buffer.Append(dateTime.Day.ToString("00")); // time, rendered if any time field is not zero if (dateTime.HasTime) { // hours and minutes buffer.Append('T'); buffer.Append(dateTime.Hour.ToString("00")); buffer.Append(':'); buffer.Append(dateTime.Minute.ToString("00")); // seconds and nanoseconds if (dateTime.Second != 0 || dateTime.Nanosecond != 0) { buffer.Append(':'); var seconds = dateTime.Second + dateTime.Nanosecond / 1e9d; buffer.AppendFormat("{0:00.#########}", seconds); } // time zone if (dateTime.HasTimeZone) { // used to calculate the time zone offset incl. Daylight Savings var timeInMillis = dateTime.Calendar.GetTimeInMillis(); var offset = (int) dateTime.TimeZone.GetUtcOffset(XmpDateTime.UnixTimeToDateTimeOffset(timeInMillis).DateTime).TotalMilliseconds; if (offset == 0) { // UTC buffer.Append('Z'); } else { var thours = offset / 3600000; var tminutes = Math.Abs(offset % 3600000 / 60000); buffer.Append(thours.ToString("+00;-00")); buffer.Append(tminutes.ToString(":00")); } } } } return buffer.ToString(); }
/// <seealso cref= XMPMeta#SetPropertyDate(String, String, XMPDateTime) </seealso> public virtual void SetPropertyDate(string schemaNs, string propName, IXmpDateTime propValue) { SetProperty(schemaNs, propName, propValue, null); }
/// <summary> /// Convert from <code>XMPDateTime</code> to string. /// </summary> /// <param name="value"> /// an <code>XMPDateTime</code> </param> /// <returns> The string representation of the long. </returns> public static string ConvertFromDate(IXmpDateTime value) { return(Iso8601Converter.Render(value)); }