Beispiel #1
0
        /// <summary>
        /// Decodes a version value and writes the time to the console.
        /// </summary>
        /// <param name="scheme">The version scheme specification of the version value.</param>
        /// <param name="value">The version value to decode.</param>
        public static void ShowDecode(string scheme, string value)
        {
            SchemeData data = ParseScheme(scheme);

            DateTime time = DateTime.MinValue;

            switch (data.SchemeType)
            {
            case SchemeType.Readable:
                time = DateTime.ParseExact(value, data.TimeFormat, CultureInfo.InvariantCulture).ToUniversalTime();
                break;

            case SchemeType.DottedDecimal:
                time = DecodeDecimal(value, data.IntervalSeconds, data.BaseYear);
                break;

            case SchemeType.BaseEncoded:
                time = DecodeBase(value, data.Alphabet, data.IntervalSeconds, data.BaseYear);
                break;

            case SchemeType.Hours:
                time = DecodeHours(value, data.BaseYear, data.BaseMonth);
                break;
            }
            if (time == DateTime.MinValue)
            {
                throw new ConsoleException("Invalid revision ID value.", ExitCodes.InvalidRevId);
            }

            Console.WriteLine(time.ToString("yyyy-MM-dd HH:mm:ss") + " UTC");
            Console.WriteLine(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss K"));
        }
        /// <summary>
        /// Formats the current data for the specified time scheme.
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        private string FormatTimeScheme(Match match)
        {
            string     scheme = match.Value;
            SchemeData data   = ParseScheme(scheme);

            DateTimeOffset time;

            if (data.TimeSource == TimeSource.Build)
            {
                time = BuildTime;
            }
            else if (data.TimeSource == TimeSource.Author)
            {
                time = RevisionData.AuthorTime;
            }
            else
            {
                time = RevisionData.CommitTime;
            }

            switch (data.SchemeType)
            {
            case SchemeType.Readable:
                if (data.Utc)
                {
                    // This code is specific to Arizona - it gets MST then uses that to get MST with daylight saving disabled.
                    // SEE: https://stackoverflow.com/questions/12266948/remove-dst-from-datetime
                    var zone    = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
                    var newzone = TimeZoneInfo.CreateCustomTimeZone(zone.Id, zone.BaseUtcOffset, zone.DisplayName, zone.StandardName, "", null, true);
                    time = time.UtcDateTime;
                    time = TimeZoneInfo.ConvertTimeFromUtc(time.DateTime, newzone);
                }
                return(time.ToString(data.TimeFormat, CultureInfo.InvariantCulture));

            case SchemeType.DottedDecimal:
                return(EncodeDecimal(time, data.IntervalSeconds, data.BaseYear));

            case SchemeType.BaseEncoded:
                return(EncodeBase(time, data.Alphabet, data.IntervalSeconds, data.BaseYear, data.MinLength, data.UpperCase));

            case SchemeType.Hours:
                return(EncodeHours(time, data.BaseYear, data.BaseMonth));
            }

            // Return match unprocessed (should not happen)
            return(scheme);
        }
Beispiel #3
0
        /// <summary>
        /// Formats the current data for the specified time scheme.
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        private string FormatTimeScheme(Match match)
        {
            string     scheme = match.Value;
            SchemeData data   = ParseScheme(scheme);

            DateTimeOffset time;

            if (data.TimeSource == TimeSource.Build)
            {
                time = BuildTime;
            }
            else if (data.TimeSource == TimeSource.Author)
            {
                time = RevisionData.AuthorTime;
            }
            else
            {
                time = RevisionData.CommitTime;
            }

            switch (data.SchemeType)
            {
            case SchemeType.Readable:
                if (data.Utc)
                {
                    time = time.UtcDateTime;
                }
                return(time.ToString(data.TimeFormat, CultureInfo.InvariantCulture));

            case SchemeType.DottedDecimal:
                return(EncodeDecimal(time, data.IntervalSeconds, data.BaseYear));

            case SchemeType.BaseEncoded:
                return(EncodeBase(time, data.Alphabet, data.IntervalSeconds, data.BaseYear, data.MinLength, data.UpperCase));

            case SchemeType.Hours:
                return(EncodeHours(time, data.BaseYear, data.BaseMonth));
            }

            // Return match unprocessed (should not happen)
            return(scheme);
        }
Beispiel #4
0
        /// <summary>
        /// Predicts the version values of the next 10 intervals and writes them to the console.
        /// </summary>
        /// <param name="scheme">The version scheme specification of the version values to generate.</param>
        public static void PredictValue(string scheme)
        {
            SchemeData data = ParseScheme(scheme);

            if (data.SchemeType == SchemeType.Readable)
            {
                throw new ConsoleException("Unsupported scheme type for predicting.", ExitCodes.InvalidScheme);
            }

            // Start with the current UTC time
            DateTimeOffset time = DateTime.UtcNow;

            // Align current time to interval boundaries
            long intervalTicks = TimeSpan.FromSeconds(data.IntervalSeconds).Ticks;

            time = new DateTime(time.Ticks / intervalTicks * intervalTicks, DateTimeKind.Utc);

            // Print the next 20 interval version values
            for (int i = 0; i < 20; i++)
            {
                Console.Write(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm K") + " = ");
                switch (data.SchemeType)
                {
                case SchemeType.DottedDecimal:
                    Console.WriteLine(EncodeDecimal(time, data.IntervalSeconds, data.BaseYear));
                    break;

                case SchemeType.BaseEncoded:
                    Console.WriteLine(EncodeBase(time, data.Alphabet, data.IntervalSeconds, data.BaseYear, data.MinLength, data.UpperCase));
                    break;

                case SchemeType.Hours:
                    Console.WriteLine(EncodeHours(time, data.BaseYear, data.BaseMonth));
                    break;
                }
                time = time.AddSeconds(data.IntervalSeconds);
            }
        }
        /// <summary>
        /// Parses a version scheme specification.
        /// </summary>
        /// <param name="scheme">The version scheme specification to parse.</param>
        /// <returns>The parsed scheme data.</returns>
        private static SchemeData ParseScheme(string scheme)
        {
            SchemeData data = new SchemeData();

            Match match;
            string sourceStr = null;
            string timeComponents = null;
            string timeSeparator = null;
            int numberBase = 0;
            int intervalValue = 0;
            string intervalType = null;

            // Split scheme string
            if ((match = Regex.Match(scheme, @"^\{?([abc]):(u?)(ymd|hms|hm|h)([-.:]?)\}?$")).Success)
            {
                data.SchemeType = SchemeType.Readable;
                sourceStr = match.Groups[1].Value;
                data.Utc = match.Groups[2].Value == "u";
                timeComponents = match.Groups[3].Value;
                timeSeparator = match.Groups[4].Value;
            }
            else if ((match = Regex.Match(scheme, @"^\{?([abc]):([0-9]+)([smhd]):([0-9]+)\}?$")).Success)
            {
                data.SchemeType = SchemeType.DottedDecimal;
                sourceStr = match.Groups[1].Value;
                intervalValue = int.Parse(match.Groups[2].Value);
                intervalType = match.Groups[3].Value;
                data.BaseYear = int.Parse(match.Groups[4].Value);
            }
            else if ((match = Regex.Match(scheme, @"^\{?([AaBbCc]):([0-9]+):([0-9]+)([smhd]):([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr = match.Groups[1].Value.ToLowerInvariant();
                data.UpperCase = char.IsUpper(match.Groups[1].Value[0]);
                numberBase = int.Parse(match.Groups[2].Value);
                intervalValue = int.Parse(match.Groups[3].Value);
                intervalType = match.Groups[4].Value;
                data.BaseYear = int.Parse(match.Groups[5].Value);
                if (match.Groups[6].Success)
                {
                    data.MinLength = int.Parse(match.Groups[6].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?([abc]):h:([0-9]{4})-([0-9]{2})\}?$")).Success)
            {
                data.SchemeType = SchemeType.Hours;
                sourceStr = match.Groups[1].Value;
                data.BaseYear = int.Parse(match.Groups[2].Value);
                data.BaseMonth = int.Parse(match.Groups[3].Value);
                data.IntervalSeconds = 3600;
            }

            #region Legacy formats

            else if ((match = Regex.Match(scheme, @"^\{?([Xx])min:([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr = "c";
                data.UpperCase = match.Groups[1].Value == "X";
                numberBase = 16;
                intervalValue = 1;
                intervalType = "m";
                data.BaseYear = int.Parse(match.Groups[2].Value);
                if (match.Groups[3].Success)
                {
                    data.MinLength = int.Parse(match.Groups[3].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?([Bb])(36)?min:([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr = "c";
                data.UpperCase = match.Groups[1].Value == "B";
                numberBase = match.Groups[2].Success ? 36 : 28;
                intervalValue = match.Groups[2].Success ? 10 : 20;
                intervalType = "m";
                data.BaseYear = int.Parse(match.Groups[3].Value);
                if (match.Groups[4].Success)
                {
                    data.MinLength = int.Parse(match.Groups[4].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?d(2)?min:([0-9]+)\}?$")).Success)
            {
                data.SchemeType = SchemeType.DottedDecimal;
                sourceStr = "c";
                intervalValue = match.Groups[1].Success ? 2 : 15;
                intervalType = "m";
                data.BaseYear = int.Parse(match.Groups[2].Value);
            }

            #endregion Legacy formats

            else
            {
                throw new ConsoleException("Invalid time scheme.", ExitCodes.InvalidScheme);
            }

            // Select time source
            switch (sourceStr)
            {
                case "a": data.TimeSource = TimeSource.Author; break;
                case "b": data.TimeSource = TimeSource.Build; break;
                case "c": data.TimeSource = TimeSource.Commit; break;
                default:
                    throw new ConsoleException("Invalid time source.", ExitCodes.InvalidScheme);
            }

            if (data.SchemeType == SchemeType.Readable)
            {
                // Select time format from components and separator
                switch (timeComponents + timeSeparator)
                {
                    case "ymd":
                        data.TimeFormat = "yyyyMMdd";
                        break;
                    case "ymd-":
                        data.TimeFormat = "yyyy-MM-dd";
                        break;
                    case "ymd.":
                        data.TimeFormat = "yyyy.MM.dd";
                        break;
                    case "hms":
                        data.TimeFormat = "HHmmss";
                        break;
                    case "hms-":
                        data.TimeFormat = "HH-mm-ss";
                        break;
                    case "hms.":
                        data.TimeFormat = "HH.mm.ss";
                        break;
                    case "hms:":
                        data.TimeFormat = "HH:mm:ss";
                        break;
                    case "hm":
                        data.TimeFormat = "HHmm";
                        break;
                    case "hm-":
                        data.TimeFormat = "HH-mm";
                        break;
                    case "hm.":
                        data.TimeFormat = "HH.mm";
                        break;
                    case "hm:":
                        data.TimeFormat = "HH:mm";
                        break;
                    case "h":
                        data.TimeFormat = "HH";
                        break;
                    default:
                        throw new ConsoleException("Invalid time components and separator.", ExitCodes.InvalidScheme);
                }
            }

            if (data.SchemeType == SchemeType.DottedDecimal ||
                data.SchemeType == SchemeType.BaseEncoded)
            {
                // Convert interval specification to seconds
                data.IntervalSeconds = intervalValue;
                switch (intervalType)
                {
                    case "s": break;
                    case "m": data.IntervalSeconds *= 60; break;
                    case "h": data.IntervalSeconds *= 60 * 60; break;
                    case "d": data.IntervalSeconds *= 24 * 60 * 60; break;
                }
            }

            if (data.SchemeType == SchemeType.BaseEncoded)
            {
                // Select alphabet for number base
                if (numberBase < 2 || numberBase > 36)
                {
                    throw new ConsoleException("Invalid number base.", ExitCodes.InvalidScheme);
                }
                else if (numberBase == 28)
                {
                    data.Alphabet = base28Alphabet;
                }
                else
                {
                    data.Alphabet = new char[numberBase];
                    Array.Copy(base36Alphabet, data.Alphabet, numberBase);
                }
            }
            return data;
        }
Beispiel #6
0
        /// <summary>
        /// Parses a version scheme specification.
        /// </summary>
        /// <param name="scheme">The version scheme specification to parse.</param>
        /// <returns>The parsed scheme data.</returns>
        private static SchemeData ParseScheme(string scheme)
        {
            SchemeData data = new SchemeData();

            Match  match;
            string sourceStr      = null;
            string timeComponents = null;
            string timeSeparator  = null;
            int    numberBase     = 0;
            int    intervalValue  = 0;
            string intervalType   = null;

            // Split scheme string
            if ((match = Regex.Match(scheme, @"^\{?([abc]):(u?)(ymd|hms|hm|h)([-.:]?)\}?$")).Success)
            {
                data.SchemeType = SchemeType.Readable;
                sourceStr       = match.Groups[1].Value;
                data.Utc        = match.Groups[2].Value == "u";
                timeComponents  = match.Groups[3].Value;
                timeSeparator   = match.Groups[4].Value;
            }
            else if ((match = Regex.Match(scheme, @"^\{?([abc]):([0-9]+)([smhd]):([0-9]+)\}?$")).Success)
            {
                data.SchemeType = SchemeType.DottedDecimal;
                sourceStr       = match.Groups[1].Value;
                intervalValue   = int.Parse(match.Groups[2].Value);
                intervalType    = match.Groups[3].Value;
                data.BaseYear   = int.Parse(match.Groups[4].Value);
            }
            else if ((match = Regex.Match(scheme, @"^\{?([AaBbCc]):([0-9]+):([0-9]+)([smhd]):([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr       = match.Groups[1].Value.ToLowerInvariant();
                data.UpperCase  = char.IsUpper(match.Groups[1].Value[0]);
                numberBase      = int.Parse(match.Groups[2].Value);
                intervalValue   = int.Parse(match.Groups[3].Value);
                intervalType    = match.Groups[4].Value;
                data.BaseYear   = int.Parse(match.Groups[5].Value);
                if (match.Groups[6].Success)
                {
                    data.MinLength = int.Parse(match.Groups[6].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?([abc]):h:([0-9]{4})-([0-9]{2})\}?$")).Success)
            {
                data.SchemeType      = SchemeType.Hours;
                sourceStr            = match.Groups[1].Value;
                data.BaseYear        = int.Parse(match.Groups[2].Value);
                data.BaseMonth       = int.Parse(match.Groups[3].Value);
                data.IntervalSeconds = 3600;
            }

            #region Legacy formats

            else if ((match = Regex.Match(scheme, @"^\{?([Xx])min:([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr       = "c";
                data.UpperCase  = match.Groups[1].Value == "X";
                numberBase      = 16;
                intervalValue   = 1;
                intervalType    = "m";
                data.BaseYear   = int.Parse(match.Groups[2].Value);
                if (match.Groups[3].Success)
                {
                    data.MinLength = int.Parse(match.Groups[3].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?([Bb])(36)?min:([0-9]+)(?::([0-9]+))?\}?$")).Success)
            {
                data.SchemeType = SchemeType.BaseEncoded;
                sourceStr       = "c";
                data.UpperCase  = match.Groups[1].Value == "B";
                numberBase      = match.Groups[2].Success ? 36 : 28;
                intervalValue   = match.Groups[2].Success ? 10 : 20;
                intervalType    = "m";
                data.BaseYear   = int.Parse(match.Groups[3].Value);
                if (match.Groups[4].Success)
                {
                    data.MinLength = int.Parse(match.Groups[4].Value);
                }
            }
            else if ((match = Regex.Match(scheme, @"^\{?d(2)?min:([0-9]+)\}?$")).Success)
            {
                data.SchemeType = SchemeType.DottedDecimal;
                sourceStr       = "c";
                intervalValue   = match.Groups[1].Success ? 2 : 15;
                intervalType    = "m";
                data.BaseYear   = int.Parse(match.Groups[2].Value);
            }

            #endregion Legacy formats

            else
            {
                throw new ConsoleException("Invalid time scheme.", ExitCodes.InvalidScheme);
            }

            // Select time source
            switch (sourceStr)
            {
            case "a": data.TimeSource = TimeSource.Author; break;

            case "b": data.TimeSource = TimeSource.Build; break;

            case "c": data.TimeSource = TimeSource.Commit; break;

            default:
                throw new ConsoleException("Invalid time source.", ExitCodes.InvalidScheme);
            }

            if (data.SchemeType == SchemeType.Readable)
            {
                // Select time format from components and separator
                switch (timeComponents + timeSeparator)
                {
                case "ymd":
                    data.TimeFormat = "yyyyMMdd";
                    break;

                case "ymd-":
                    data.TimeFormat = "yyyy-MM-dd";
                    break;

                case "ymd.":
                    data.TimeFormat = "yyyy.MM.dd";
                    break;

                case "hms":
                    data.TimeFormat = "HHmmss";
                    break;

                case "hms-":
                    data.TimeFormat = "HH-mm-ss";
                    break;

                case "hms.":
                    data.TimeFormat = "HH.mm.ss";
                    break;

                case "hms:":
                    data.TimeFormat = "HH:mm:ss";
                    break;

                case "hm":
                    data.TimeFormat = "HHmm";
                    break;

                case "hm-":
                    data.TimeFormat = "HH-mm";
                    break;

                case "hm.":
                    data.TimeFormat = "HH.mm";
                    break;

                case "hm:":
                    data.TimeFormat = "HH:mm";
                    break;

                case "h":
                    data.TimeFormat = "HH";
                    break;

                default:
                    throw new ConsoleException("Invalid time components and separator.", ExitCodes.InvalidScheme);
                }
            }

            if (data.SchemeType == SchemeType.DottedDecimal ||
                data.SchemeType == SchemeType.BaseEncoded)
            {
                // Convert interval specification to seconds
                data.IntervalSeconds = intervalValue;
                switch (intervalType)
                {
                case "s": break;

                case "m": data.IntervalSeconds *= 60; break;

                case "h": data.IntervalSeconds *= 60 * 60; break;

                case "d": data.IntervalSeconds *= 24 * 60 * 60; break;
                }
            }

            if (data.SchemeType == SchemeType.BaseEncoded)
            {
                // Select alphabet for number base
                if (numberBase < 2 || numberBase > 36)
                {
                    throw new ConsoleException("Invalid number base.", ExitCodes.InvalidScheme);
                }
                else if (numberBase == 28)
                {
                    data.Alphabet = base28Alphabet;
                }
                else
                {
                    data.Alphabet = new char[numberBase];
                    Array.Copy(base36Alphabet, data.Alphabet, numberBase);
                }
            }
            return(data);
        }