/// <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>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 <code>XMPDateTime</code> variable containing the time to be modified.</param> /// <returns>Returns an updated <code>XMPDateTime</code>-object.</returns> public static XMPDateTime ConvertToLocalTime(XMPDateTime dateTime) { long timeInMillis = dateTime.GetCalendar().GetTimeInMillis(); // has automatically local timezone Sharpen.GregorianCalendar cal = new Sharpen.GregorianCalendar(); cal.SetTimeInMillis(timeInMillis); return new XMPDateTimeImpl(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 <code>XMPDateTime</code> variable containing the time to /// be modified. /// </param> /// <returns>Returns an updated <code>XMPDateTime</code>-object.</returns> public static XMPDateTime ConvertToUTCTime(XMPDateTime dateTime) { long timeInMillis = dateTime.GetCalendar().GetTimeInMillis(); Sharpen.GregorianCalendar cal = new Sharpen.GregorianCalendar(Utc); cal.SetGregorianChange(Sharpen.Extensions.CreateDate(long.MinValue)); cal.SetTimeInMillis(timeInMillis); return new XMPDateTimeImpl(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 <code>XMPDateTime</code> variable containing the time to /// be modified. /// </param> /// <returns>Returns an updated <code>XMPDateTime</code>-object.</returns> public static XMPDateTime ConvertToUTCTime(XMPDateTime dateTime) { long timeInMillis = dateTime.GetCalendar().GetTimeInMillis(); Sharpen.GregorianCalendar cal = new Sharpen.GregorianCalendar(Utc); cal.SetGregorianChange(Sharpen.Extensions.CreateDate(long.MinValue)); cal.SetTimeInMillis(timeInMillis); return(new XMPDateTimeImpl(cal)); }
public virtual void Never() { GregorianCalendar cal = new GregorianCalendar(SystemReader.GetInstance().GetTimeZone (), SystemReader.GetInstance().GetLocale()); DateTime parse = GitDateParser.Parse("never", cal); NUnit.Framework.Assert.AreEqual(GitDateParser.NEVER, parse); parse = GitDateParser.Parse("never", null); NUnit.Framework.Assert.AreEqual(GitDateParser.NEVER, parse); }
/// <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 <code>XMPDateTime</code> variable containing the time to be modified.</param> /// <returns>Returns an updated <code>XMPDateTime</code>-object.</returns> public static XMPDateTime ConvertToLocalTime(XMPDateTime dateTime) { long timeInMillis = dateTime.GetCalendar().GetTimeInMillis(); // has automatically local timezone Sharpen.GregorianCalendar cal = new Sharpen.GregorianCalendar(); cal.SetTimeInMillis(timeInMillis); return(new XMPDateTimeImpl(cal)); }
public virtual void TestExtract_DigitizedDateTime() { DateTime? actual = _directory.GetDate(XmpDirectory.TagDatetimeDigitized); // Underlying string value (in XMP data) is: 2010-12-12T12:41:35.00+01:00 Sharpen.Tests.AreEqual(new SimpleDateFormat("hh:mm:ss dd MM yyyy Z").Parse("11:41:35 12 12 2010 +0000"), actual); // assertEquals(new SimpleDateFormat("HH:mm:ss dd MMM yyyy Z").parse("12:41:35 12 Dec 2010 +0100"), actual); Sharpen.Calendar calendar = new Sharpen.GregorianCalendar(2010, 12 - 1, 12, 11, 41, 35); calendar.SetTimeZone(Sharpen.Extensions.GetTimeZone("GMT")); Sharpen.Tests.AreEqual(calendar.GetTime(), actual.Value); }
public virtual void TestExtract_DigitizedDateTime() { DateTime?actual = _directory.GetDate(XmpDirectory.TagDatetimeDigitized); // Underlying string value (in XMP data) is: 2010-12-12T12:41:35.00+01:00 Sharpen.Tests.AreEqual(new SimpleDateFormat("hh:mm:ss dd MM yyyy Z").Parse("11:41:35 12 12 2010 +0000"), actual); // assertEquals(new SimpleDateFormat("HH:mm:ss dd MMM yyyy Z").parse("12:41:35 12 Dec 2010 +0100"), actual); Sharpen.Calendar calendar = new Sharpen.GregorianCalendar(2010, 12 - 1, 12, 11, 41, 35); calendar.SetTimeZone(Sharpen.Extensions.GetTimeZone("GMT")); Sharpen.Tests.AreEqual(calendar.GetTime(), actual.Value); }
public virtual void Yesterday() { GregorianCalendar cal = new GregorianCalendar(SystemReader.GetInstance().GetTimeZone (), SystemReader.GetInstance().GetLocale()); DateTime parse = GitDateParser.Parse("yesterday", cal); cal.Add(Calendar.DATE, -1); cal.Set(Calendar.HOUR_OF_DAY, 0); cal.Set(Calendar.MINUTE, 0); cal.Set(Calendar.SECOND, 0); cal.Set(Calendar.MILLISECOND, 0); cal.Set(Calendar.MILLISECOND, 0); NUnit.Framework.Assert.AreEqual(cal.GetTime(), parse); }
public virtual void BadlyFormattedWithExplicitRef() { Calendar @ref = new GregorianCalendar(SystemReader.GetInstance().GetTimeZone(), SystemReader .GetInstance().GetLocale()); try { GitDateParser.Parse(dateStr, @ref); NUnit.Framework.Assert.Fail("The expected ParseException while parsing '" + dateStr + "' did not occur."); } catch (ParseException) { } }
/// <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; }
/// <seealso cref="Com.Adobe.Xmp.XMPDateTime.GetCalendar()"/> public virtual Sharpen.Calendar GetCalendar() { Sharpen.GregorianCalendar calendar = (Sharpen.GregorianCalendar)Sharpen.Calendar.GetInstance(CultureInfo.InvariantCulture); calendar.SetGregorianChange(Sharpen.Extensions.CreateDate(long.MinValue)); if (hasTimeZone) { calendar.SetTimeZone(timeZone); } calendar.Set(Sharpen.CalendarEnum.Year, year); calendar.Set(Sharpen.CalendarEnum.Month, month - 1); calendar.Set(Sharpen.CalendarEnum.DayOfMonth, day); calendar.Set(Sharpen.CalendarEnum.HourOfDay, hour); calendar.Set(Sharpen.CalendarEnum.Minute, minute); calendar.Set(Sharpen.CalendarEnum.Second, second); calendar.Set(Sharpen.CalendarEnum.Millisecond, nanoSeconds / 1000000); return(calendar); }
/// <exception cref="System.IO.IOException"/> private void ProcessTag([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount) { int tagIdentifier = tagType | (directoryType << 8); // Some images have been seen that specify a zero byte tag, which cannot be of much use. // We elect here to completely ignore the tag. The IPTC specification doesn't mention // anything about the interpretation of this situation. // https://raw.githubusercontent.com/wiki/drewnoakes/metadata-extractor/docs/IPTC-IIMV4.2.pdf if (tagByteCount == 0) { directory.SetString(tagIdentifier, string.Empty); return; } string @string = null; switch (tagIdentifier) { case IptcDirectory.TagCodedCharacterSet: { sbyte[] bytes = reader.GetBytes(tagByteCount); string charset = Iso2022Converter.ConvertISO2022CharsetToJavaCharset(bytes); if (charset == null) { // Unable to determine the charset, so fall through and treat tag as a regular string @string = Sharpen.Runtime.GetStringForBytes(bytes); break; } directory.SetString(tagIdentifier, charset); return; } case IptcDirectory.TagEnvelopeRecordVersion: case IptcDirectory.TagApplicationRecordVersion: case IptcDirectory.TagFileVersion: case IptcDirectory.TagArmVersion: case IptcDirectory.TagProgramVersion: { // short if (tagByteCount >= 2) { int shortValue = reader.GetUInt16(); reader.Skip(tagByteCount - 2); directory.SetInt(tagIdentifier, shortValue); return; } break; } case IptcDirectory.TagUrgency: { // byte directory.SetInt(tagIdentifier, reader.GetUInt8()); reader.Skip(tagByteCount - 1); return; } case IptcDirectory.TagReleaseDate: case IptcDirectory.TagDateCreated: { // Date object if (tagByteCount >= 8) { @string = reader.GetString(tagByteCount); try { int year = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4)); int month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1; int day = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8)); DateTime date = new Sharpen.GregorianCalendar(year, month, day).GetTime(); directory.SetDate(tagIdentifier, date); return; } catch (FormatException) { } } else { // fall through and we'll process the 'string' value below reader.Skip(tagByteCount); } goto case IptcDirectory.TagReleaseTime; } case IptcDirectory.TagReleaseTime: case IptcDirectory.TagTimeCreated: default: { break; } } // time... // fall through // If we haven't returned yet, treat it as a string // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value if (@string == null) { string encoding = directory.GetString(IptcDirectory.TagCodedCharacterSet); if (encoding != null) { @string = reader.GetString(tagByteCount, encoding); } else { sbyte[] bytes_1 = reader.GetBytes(tagByteCount); encoding = Iso2022Converter.GuessEncoding(bytes_1); @string = encoding != null?Sharpen.Runtime.GetStringForBytes(bytes_1, encoding) : Sharpen.Runtime.GetStringForBytes(bytes_1); } } if (directory.ContainsTag(tagIdentifier)) { // this fancy string[] business avoids using an ArrayList for performance reasons string[] oldStrings = directory.GetStringArray(tagIdentifier); string[] newStrings; if (oldStrings == null) { newStrings = new string[1]; } else { newStrings = new string[oldStrings.Length + 1]; System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length); } newStrings[newStrings.Length - 1] = @string; directory.SetStringArray(tagIdentifier, newStrings); } else { directory.SetString(tagIdentifier, @string); } }
/// <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="System.IO.IOException"/> private void ProcessTag(SequentialReader reader, Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount) { int tagIdentifier = tagType | (directoryType << 8); string @string = null; switch (tagIdentifier) { case IptcDirectory.TagApplicationRecordVersion: { // short int shortValue = reader.GetUInt16(); reader.Skip(tagByteCount - 2); directory.SetInt(tagIdentifier, shortValue); return; } case IptcDirectory.TagUrgency: { // byte directory.SetInt(tagIdentifier, reader.GetUInt8()); reader.Skip(tagByteCount - 1); return; } case IptcDirectory.TagReleaseDate: case IptcDirectory.TagDateCreated: { // Date object if (tagByteCount >= 8) { @string = reader.GetString(tagByteCount); try { int year = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4)); int month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1; int day = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8)); DateTime date = new Sharpen.GregorianCalendar(year, month, day).GetTime(); directory.SetDate(tagIdentifier, date); return; } catch (FormatException) { } } else { // fall through and we'll process the 'string' value below reader.Skip(tagByteCount); } goto case IptcDirectory.TagReleaseTime; } case IptcDirectory.TagReleaseTime: case IptcDirectory.TagTimeCreated: default: { break; } } // time... // fall through // If we haven't returned yet, treat it as a string // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value if (@string == null) { @string = reader.GetString(tagByteCount, Runtime.GetProperty("file.encoding")); } // "ISO-8859-1" if (directory.ContainsTag(tagIdentifier)) { // this fancy string[] business avoids using an ArrayList for performance reasons string[] oldStrings = directory.GetStringArray(tagIdentifier); string[] newStrings; if (oldStrings == null) { newStrings = new string[1]; } else { newStrings = new string[oldStrings.Length + 1]; System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length); } newStrings[newStrings.Length - 1] = @string; directory.SetStringArray(tagIdentifier, newStrings); } else { directory.SetString(tagIdentifier, @string); } }
/// <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); }
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); }
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); }
/** * Date/Time utilities */ private static void CoverDateTime() { writeMajorLabel ("Test date/time utilities and special values"); var date1 = XmpDateTimeFactory.Create(2000, 1, 31, 12, 34, 56, -1); date1.TimeZone = TimeZoneInfo.FindSystemTimeZoneById("PST"); var date2 = XmpDateTimeFactory.Create(0, 0, 0, 0, 0, 0, 0); GregorianCalendar cal = new GregorianCalendar(2007, 1, 28); var date3 = XmpDateTimeFactory.CreateFromCalendar(cal); var currentDateTime = XmpDateTimeFactory.GetCurrentDateTime(); log.WriteLine("Print date 2000 Jan 31 12:34:56 PST = {0}", date1); log.WriteLine("Print zero date = {0}", date2); log.WriteLine("Print date created by a calendar = {0}", date3); log.WriteLine("Print current date = {0}", currentDateTime); log.WriteLine(); }
/// <exception cref="System.IO.IOException"/> private void ProcessTag([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount) { int tagIdentifier = tagType | (directoryType << 8); // Some images have been seen that specify a zero byte tag, which cannot be of much use. // We elect here to completely ignore the tag. The IPTC specification doesn't mention // anything about the interpretation of this situation. // https://raw.githubusercontent.com/wiki/drewnoakes/metadata-extractor/docs/IPTC-IIMV4.2.pdf if (tagByteCount == 0) { directory.SetString(tagIdentifier, string.Empty); return; } string @string = null; switch (tagIdentifier) { case IptcDirectory.TagCodedCharacterSet: { sbyte[] bytes = reader.GetBytes(tagByteCount); string charset = Iso2022Converter.ConvertISO2022CharsetToJavaCharset(bytes); if (charset == null) { // Unable to determine the charset, so fall through and treat tag as a regular string @string = Sharpen.Runtime.GetStringForBytes(bytes); break; } directory.SetString(tagIdentifier, charset); return; } case IptcDirectory.TagEnvelopeRecordVersion: case IptcDirectory.TagApplicationRecordVersion: case IptcDirectory.TagFileVersion: case IptcDirectory.TagArmVersion: case IptcDirectory.TagProgramVersion: { // short if (tagByteCount >= 2) { int shortValue = reader.GetUInt16(); reader.Skip(tagByteCount - 2); directory.SetInt(tagIdentifier, shortValue); return; } break; } case IptcDirectory.TagUrgency: { // byte directory.SetInt(tagIdentifier, reader.GetUInt8()); reader.Skip(tagByteCount - 1); return; } case IptcDirectory.TagReleaseDate: case IptcDirectory.TagDateCreated: { // Date object if (tagByteCount >= 8) { @string = reader.GetString(tagByteCount); try { int year = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4)); int month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1; int day = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8)); DateTime date = new Sharpen.GregorianCalendar(year, month, day).GetTime(); directory.SetDate(tagIdentifier, date); return; } catch (FormatException) { } } else { // fall through and we'll process the 'string' value below reader.Skip(tagByteCount); } goto case IptcDirectory.TagReleaseTime; } case IptcDirectory.TagReleaseTime: case IptcDirectory.TagTimeCreated: default: { break; } } // time... // fall through // If we haven't returned yet, treat it as a string // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value if (@string == null) { string encoding = directory.GetString(IptcDirectory.TagCodedCharacterSet); if (encoding != null) { @string = reader.GetString(tagByteCount, encoding); } else { sbyte[] bytes_1 = reader.GetBytes(tagByteCount); encoding = Iso2022Converter.GuessEncoding(bytes_1); @string = encoding != null ? Sharpen.Runtime.GetStringForBytes(bytes_1, encoding) : Sharpen.Runtime.GetStringForBytes(bytes_1); } } if (directory.ContainsTag(tagIdentifier)) { // this fancy string[] business avoids using an ArrayList for performance reasons string[] oldStrings = directory.GetStringArray(tagIdentifier); string[] newStrings; if (oldStrings == null) { newStrings = new string[1]; } else { newStrings = new string[oldStrings.Length + 1]; System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length); } newStrings[newStrings.Length - 1] = @string; directory.SetStringArray(tagIdentifier, newStrings); } else { directory.SetString(tagIdentifier, @string); } }