diff --git a/VisualCard.Calendar/Parsers/VCalendarConstants.cs b/VisualCard.Calendar/Parsers/VCalendarConstants.cs index 4933fd5..a212125 100644 --- a/VisualCard.Calendar/Parsers/VCalendarConstants.cs +++ b/VisualCard.Calendar/Parsers/VCalendarConstants.cs @@ -76,6 +76,7 @@ internal static class VCalendarConstants internal const string _tzUrlSpecifier = "TZURL"; internal const string _recurseSpecifier = "RRULE"; internal const string _recDateSpecifier = "RDATE"; + internal const string _dateCompletedSpecifier = "COMPLETED"; internal const string _xSpecifier = "X-"; internal const string _typeArgumentSpecifier = "TYPE="; internal const string _valueArgumentSpecifier = "VALUE="; diff --git a/VisualCard.Calendar/Parsers/VCalendarParserTools.cs b/VisualCard.Calendar/Parsers/VCalendarParserTools.cs index 2d49a1a..1b62403 100644 --- a/VisualCard.Calendar/Parsers/VCalendarParserTools.cs +++ b/VisualCard.Calendar/Parsers/VCalendarParserTools.cs @@ -24,6 +24,8 @@ using VisualCard.Calendar.Parts.Implementations.Event; using VisualCard.Parts.Enums; using System.Linq; +using VisualCard.Calendar.Parts.Implementations.TimeZone; +using VisualCard.Calendar.Parts.Implementations.Todo; namespace VisualCard.Calendar.Parsers { @@ -77,6 +79,7 @@ internal static bool EnumArrayTypeSupported(CalendarPartsArrayEnum partsArrayEnu CalendarPartsArrayEnum.DateCreatedAlt => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo)), CalendarPartsArrayEnum.DateStart => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarFreeBusy), typeof(CalendarStandard), typeof(CalendarDaylight)), CalendarPartsArrayEnum.DateEnd => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarFreeBusy)), + CalendarPartsArrayEnum.DateCompleted => TypeMatch(componentType, typeof(CalendarTodo)), CalendarPartsArrayEnum.DateStamp => calendarVersion.Major == 2 && TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarJournal), typeof(CalendarFreeBusy)), CalendarPartsArrayEnum.TimeZoneName => calendarVersion.Major == 2 && TypeMatch(componentType, typeof(CalendarTimeZone)), CalendarPartsArrayEnum.RecDate => calendarVersion.Major == 2 && TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarJournal), typeof(CalendarStandard), typeof(CalendarDaylight)), @@ -133,6 +136,7 @@ internal static string GetPrefixFromPartsArrayEnum(CalendarPartsArrayEnum partsA CalendarPartsArrayEnum.DateCreatedAlt => VCalendarConstants._created1Specifier, CalendarPartsArrayEnum.DateStart => VCalendarConstants._dateStartSpecifier, CalendarPartsArrayEnum.DateEnd => VCalendarConstants._dateEndSpecifier, + CalendarPartsArrayEnum.DateCompleted => VCalendarConstants._dateCompletedSpecifier, CalendarPartsArrayEnum.DateStamp => VCalendarConstants._dateStampSpecifier, CalendarPartsArrayEnum.TimeZoneName => VCalendarConstants._tzNameSpecifier, CalendarPartsArrayEnum.RecDate => VCalendarConstants._recDateSpecifier, @@ -167,6 +171,8 @@ internal static (CalendarPartsArrayEnum, PartCardinality) GetPartsArrayEnumFromT return (CalendarPartsArrayEnum.DateStart, PartCardinality.ShouldBeOne); else if (partsArrayType == typeof(DateEndInfo)) return (CalendarPartsArrayEnum.DateEnd, PartCardinality.MayBeOne); + else if (partsArrayType == typeof(DateCompletedInfo)) + return (CalendarPartsArrayEnum.DateCompleted, PartCardinality.MayBeOne); else if (partsArrayType == typeof(DateStampInfo)) return (CalendarPartsArrayEnum.DateStamp, PartCardinality.MayBeOne); else if (partsArrayType == typeof(TimeZoneNameInfo)) @@ -192,6 +198,7 @@ internal static (PartType type, object enumeration, Type? enumType, Func (PartType.PartsArray, CalendarPartsArrayEnum.DateCreatedAlt, typeof(DateCreatedInfo), DateCreatedInfo.FromStringVcalendarStatic, "", "", []), VCalendarConstants._dateStartSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateStart, typeof(DateStartInfo), DateStartInfo.FromStringVcalendarStatic, "", "", []), VCalendarConstants._dateEndSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateEnd, typeof(DateEndInfo), DateEndInfo.FromStringVcalendarStatic, "", "", []), + VCalendarConstants._dateCompletedSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateCompleted, typeof(DateCompletedInfo), DateCompletedInfo.FromStringVcalendarStatic, "", "", []), VCalendarConstants._dateStampSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateStamp, typeof(DateStampInfo), DateStampInfo.FromStringVcalendarStatic, "", "", []), VCalendarConstants._tzNameSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.TimeZoneName, typeof(TimeZoneNameInfo), TimeZoneNameInfo.FromStringVcalendarStatic, "", "", []), VCalendarConstants._recDateSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.RecDate, typeof(RecDateInfo), RecDateInfo.FromStringVcalendarStatic, "", "", []), diff --git a/VisualCard.Calendar/Parts/Enums/CalendarPartsArrayEnum.cs b/VisualCard.Calendar/Parts/Enums/CalendarPartsArrayEnum.cs index 40f0a9b..099bd2b 100644 --- a/VisualCard.Calendar/Parts/Enums/CalendarPartsArrayEnum.cs +++ b/VisualCard.Calendar/Parts/Enums/CalendarPartsArrayEnum.cs @@ -84,5 +84,9 @@ public enum CalendarPartsArrayEnum /// Recurrence date and time (event, todo, journal, or standard/daylight timezone components) /// RecDate, + /// + /// To-do date completion + /// + DateCompleted, } } diff --git a/VisualCard.Calendar/Parts/Implementations/TimeZone/TimeZoneNameInfo.cs b/VisualCard.Calendar/Parts/Implementations/TimeZone/TimeZoneNameInfo.cs index 7429bec..1224353 100644 --- a/VisualCard.Calendar/Parts/Implementations/TimeZone/TimeZoneNameInfo.cs +++ b/VisualCard.Calendar/Parts/Implementations/TimeZone/TimeZoneNameInfo.cs @@ -22,7 +22,7 @@ using System.Diagnostics; using System.Text.RegularExpressions; -namespace VisualCard.Calendar.Parts.Implementations +namespace VisualCard.Calendar.Parts.Implementations.TimeZone { /// /// Calendar time zone name info diff --git a/VisualCard.Calendar/Parts/Implementations/Todo/DateCompletedInfo.cs b/VisualCard.Calendar/Parts/Implementations/Todo/DateCompletedInfo.cs new file mode 100644 index 0000000..aac24e6 --- /dev/null +++ b/VisualCard.Calendar/Parts/Implementations/Todo/DateCompletedInfo.cs @@ -0,0 +1,111 @@ +// +// VisualCard Copyright (C) 2021-2024 Aptivi +// +// This file is part of VisualCard +// +// VisualCard is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// VisualCard is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using System.Diagnostics; +using VisualCard.Parsers; + +namespace VisualCard.Calendar.Parts.Implementations.Todo +{ + /// + /// Card date completed info + /// + [DebuggerDisplay("Date Completed = {DateCompleted}")] + public class DateCompletedInfo : BaseCalendarPartInfo, IEquatable + { + /// + /// The to-do completion date + /// + public DateTime DateCompleted { get; } + + internal static BaseCalendarPartInfo FromStringVcalendarStatic(string value, string[] finalArgs, string[] elementTypes, string valueType, Version cardVersion) => + new DateCompletedInfo().FromStringVcalendarInternal(value, finalArgs, elementTypes, valueType, cardVersion); + + internal override string ToStringVcalendarInternal(Version cardVersion) => + $"{VcardParserTools.SavePosixDate(DateCompleted)}"; + + internal override BaseCalendarPartInfo FromStringVcalendarInternal(string value, string[] finalArgs, string[] elementTypes, string valueType, Version cardVersion) + { + // Populate the fields + DateTime completed = VcardParserTools.ParsePosixDate(value); + + // Add the fetched information + DateCompletedInfo _time = new(finalArgs, elementTypes, valueType, completed); + return _time; + } + + /// + public override bool Equals(object obj) => + Equals((DateCompletedInfo)obj); + + /// + /// Checks to see if both the parts are equal + /// + /// The target instance to check to see if they equal + /// True if all the part elements are equal. Otherwise, false. + public bool Equals(DateCompletedInfo other) => + Equals(this, other); + + /// + /// Checks to see if both the parts are equal + /// + /// The source instance to check to see if they equal + /// The target instance to check to see if they equal + /// True if all the part elements are equal. Otherwise, false. + public bool Equals(DateCompletedInfo source, DateCompletedInfo target) + { + // We can't perform this operation on null. + if (source is null || target is null) + return false; + + // Check all the properties + return + source.DateCompleted == target.DateCompleted + ; + } + + /// + public override int GetHashCode() + { + int hashCode = 47832270; + hashCode = hashCode * -1521134295 + base.GetHashCode(); + hashCode = hashCode * -1521134295 + DateCompleted.GetHashCode(); + return hashCode; + } + + /// + public static bool operator ==(DateCompletedInfo left, DateCompletedInfo right) => + left.Equals(right); + + /// + public static bool operator !=(DateCompletedInfo left, DateCompletedInfo right) => + !(left == right); + + internal override bool EqualsInternal(BaseCalendarPartInfo source, BaseCalendarPartInfo target) => + (DateCompletedInfo)source == (DateCompletedInfo)target; + + internal DateCompletedInfo() { } + + internal DateCompletedInfo(string[] arguments, string[] elementTypes, string valueType, DateTime rev) : + base(arguments, elementTypes, valueType) + { + DateCompleted = rev; + } + } +}