using System; using System.Globalization; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.X509 { public class Time : Asn1Encodable, IAsn1Choice { public static Time GetInstance(object obj) { if (obj == null) return null; if (obj is Time time) return time; if (obj is Asn1UtcTime utcTime) return new Time(utcTime); if (obj is Asn1GeneralizedTime generalizedTime) return new Time(generalizedTime); throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), nameof(obj)); } public static Time GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) => Asn1Utilities.GetInstanceChoice(taggedObject, declaredExplicit, GetInstance); public static Time GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit) => Asn1Utilities.GetTaggedChoice(taggedObject, declaredExplicit, GetInstance); public static Time GetOptional(Asn1Encodable element) { if (element == null) throw new ArgumentNullException(nameof(element)); if (element is Time time) return time; Asn1UtcTime utcTime = Asn1UtcTime.GetOptional(element); if (utcTime != null) return new Time(utcTime); Asn1GeneralizedTime generalizedTime = Asn1GeneralizedTime.GetOptional(element); if (generalizedTime != null) return new Time(generalizedTime); return null; } private readonly Asn1Object m_timeObject; public Time(Asn1GeneralizedTime generalizedTime) { m_timeObject = generalizedTime ?? throw new ArgumentNullException(nameof(generalizedTime)); } public Time(Asn1UtcTime utcTime) { if (utcTime == null) throw new ArgumentNullException(nameof(utcTime)); // Validate utcTime is in the appropriate year range utcTime.ToDateTime(2049); m_timeObject = utcTime; } /** * creates a time object from a given date - if the date is between 1950 * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime * is used. */ public Time(DateTime date) { DateTime utc = date.ToUniversalTime(); if (utc.Year < 1950 || utc.Year > 2049) { m_timeObject = Rfc5280Asn1Utilities.CreateGeneralizedTime(utc); } else { m_timeObject = Rfc5280Asn1Utilities.CreateUtcTime(utc); } } /// /// Return our time as DateTime. /// /// A date time. public DateTime ToDateTime() { try { if (m_timeObject is Asn1UtcTime utcTime) return utcTime.ToDateTime(2049); return ((Asn1GeneralizedTime)m_timeObject).ToDateTime(); } catch (FormatException e) { // this should never happen throw new InvalidOperationException("invalid date string: " + e.Message); } } /** * Produce an object suitable for an Asn1OutputStream. *
         * Time ::= CHOICE {
         *             utcTime        UTCTime,
         *             generalTime    GeneralizedTime }
         * 
*/ public override Asn1Object ToAsn1Object() { return m_timeObject; } public override string ToString() { if (m_timeObject is Asn1UtcTime utcTime) return utcTime.ToDateTime(2049).ToString(@"yyyyMMddHHmmssK", DateTimeFormatInfo.InvariantInfo); if (m_timeObject is Asn1GeneralizedTime generalizedTime) return generalizedTime.ToDateTime().ToString(@"yyyyMMddHHmmss.FFFFFFFK", DateTimeFormatInfo.InvariantInfo); throw new InvalidOperationException(); } } }