#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved //----------------------------------------------------------------------------- // Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved // Web: https://www.technosoftware.com // // The source code in this file is covered under a dual-license scenario: // - Owner of a purchased license: SCLA 1.0 // - GPL V3: everybody else // // SCLA license terms accompanied with this source code. // See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf // // GNU General Public License as published by the Free Software Foundation; // version 3 of the License are accompanied with this source code. // See https://technosoftware.com/license/GPLv3License.txt // // This source code 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. //----------------------------------------------------------------------------- #endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved #region Using Directives using System; using System.Text; #endregion namespace Technosoftware.DaAeHdaClient.Hda { /// /// A time specified as either an absolute or relative value. /// [Serializable] public class TsCHdaTime { #region Fields private DateTime absoluteTime_ = DateTime.MinValue; private TsCHdaRelativeTime baseTime_ = TsCHdaRelativeTime.Now; private TsCHdaTimeOffsetCollection offsets_ = new TsCHdaTimeOffsetCollection(); #endregion #region Constructors, Destructor, Initialization /// /// Initializes the object with its default values. /// public TsCHdaTime() { } /// /// Initializes the object with an absolute time. /// /// The absolute time. public TsCHdaTime(DateTime time) { AbsoluteTime = time; } /// /// Initializes the object with a relative time. /// /// The relative time. public TsCHdaTime(string time) { var value = Parse(time); absoluteTime_ = DateTime.MinValue; baseTime_ = value.baseTime_; offsets_ = value.offsets_; } #endregion #region Properties /// /// Whether the time is a relative or absolute time. /// public bool IsRelative { get => (absoluteTime_ == DateTime.MinValue); set => absoluteTime_ = DateTime.MinValue; } /// /// The time as absolute value. /// The ApplicationInstance.TimeAsUtc property defines /// the time format (UTC or local time). /// public DateTime AbsoluteTime { get => absoluteTime_; set => absoluteTime_ = value; } /// /// The base for a relative time value. /// public TsCHdaRelativeTime BaseTime { get => baseTime_; set => baseTime_ = value; } /// /// The set of offsets to be applied to the base of a relative time. /// public TsCHdaTimeOffsetCollection Offsets => offsets_; #endregion #region Public Methods /// /// Converts a relative time to an absolute time by using the system clock. /// public DateTime ResolveTime() { // nothing special to do for absolute times. if (!IsRelative) { return absoluteTime_; } // get local time from the system. var time = DateTime.UtcNow; var years = time.Year; var months = time.Month; var days = time.Day; var hours = time.Hour; var minutes = time.Minute; var seconds = time.Second; var milliseconds = time.Millisecond; // move to the beginning of the period indicated by the base time. switch (BaseTime) { case TsCHdaRelativeTime.Year: { months = 0; days = 0; hours = 0; minutes = 0; seconds = 0; milliseconds = 0; break; } case TsCHdaRelativeTime.Month: { days = 0; hours = 0; minutes = 0; seconds = 0; milliseconds = 0; break; } case TsCHdaRelativeTime.Week: case TsCHdaRelativeTime.Day: { hours = 0; minutes = 0; seconds = 0; milliseconds = 0; break; } case TsCHdaRelativeTime.Hour: { minutes = 0; seconds = 0; milliseconds = 0; break; } case TsCHdaRelativeTime.Minute: { seconds = 0; milliseconds = 0; break; } case TsCHdaRelativeTime.Second: { milliseconds = 0; break; } } // construct base time. time = new DateTime(years, months, days, hours, minutes, seconds, milliseconds); // adjust to beginning of week. if (BaseTime == TsCHdaRelativeTime.Week && time.DayOfWeek != DayOfWeek.Sunday) { time = time.AddDays(-((int)time.DayOfWeek)); } // add offsets. foreach (TsCHdaTimeOffset offset in Offsets) { switch (offset.Type) { case TsCHdaRelativeTime.Year: { time = time.AddYears(offset.Value); break; } case TsCHdaRelativeTime.Month: { time = time.AddMonths(offset.Value); break; } case TsCHdaRelativeTime.Week: { time = time.AddDays(offset.Value * 7); break; } case TsCHdaRelativeTime.Day: { time = time.AddDays(offset.Value); break; } case TsCHdaRelativeTime.Hour: { time = time.AddHours(offset.Value); break; } case TsCHdaRelativeTime.Minute: { time = time.AddMinutes(offset.Value); break; } case TsCHdaRelativeTime.Second: { time = time.AddSeconds(offset.Value); break; } } } // return resolved time. return time; } /// /// Returns a String that represents the current Object. /// /// A String that represents the current Object. public override string ToString() { if (!IsRelative) { return OpcConvert.ToString(absoluteTime_); } var buffer = new StringBuilder(256); buffer.Append(BaseTypeToString(BaseTime)); buffer.Append(Offsets); return buffer.ToString(); } /// /// Parses a string representation of a time. /// /// The string representation to parse. /// A Time object initialized with the string. public static TsCHdaTime Parse(string buffer) { // remove trailing and leading white spaces. buffer = buffer.Trim(); var time = new TsCHdaTime(); // determine if string is a relative time. var isRelative = false; foreach (TsCHdaRelativeTime baseTime in Enum.GetValues(typeof(TsCHdaRelativeTime))) { var token = BaseTypeToString(baseTime); if (buffer.StartsWith(token)) { buffer = buffer.Substring(token.Length).Trim(); time.BaseTime = baseTime; isRelative = true; break; } } // parse an absolute time string. if (!isRelative) { time.AbsoluteTime = Convert.ToDateTime(buffer).ToUniversalTime(); return time; } // parse the offset portion of the relative time. if (buffer.Length > 0) { time.Offsets.Parse(buffer); } return time; } #endregion #region Public Methods /// /// Converts a base time to a string token. /// /// The base time value to convert. /// The string token representing the base time. private static string BaseTypeToString(TsCHdaRelativeTime baseTime) { switch (baseTime) { case TsCHdaRelativeTime.Now: { return "NOW"; } case TsCHdaRelativeTime.Second: { return "SECOND"; } case TsCHdaRelativeTime.Minute: { return "MINUTE"; } case TsCHdaRelativeTime.Hour: { return "HOUR"; } case TsCHdaRelativeTime.Day: { return "DAY"; } case TsCHdaRelativeTime.Week: { return "WEEK"; } case TsCHdaRelativeTime.Month: { return "MONTH"; } case TsCHdaRelativeTime.Year: { return "YEAR"; } } throw new ArgumentOutOfRangeException(nameof(baseTime), baseTime.ToString(), @"Invalid value for relative base time."); } #endregion } }