예제 #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 = ParseTimeScheme(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 FormatException("Invalid revision ID value: " + value);
            }

            Console.WriteLine(time.ToString("yyyy-MM-dd HH:mm:ss") + " UTC");
            Console.WriteLine(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss K"));
        }
예제 #2
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   = ParseTimeScheme(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);
        }
예제 #3
0
        /// <summary>
        /// Parses a time-based version scheme specification.
        /// </summary>
        /// <param name="scheme">The version scheme specification to parse.</param>
        /// <returns>The parsed scheme data.</returns>
        private static SchemeData ParseTimeScheme(string scheme)
        {
            var 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 FormatException("Invalid time scheme: " + scheme);
            }

            // 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 FormatException("Invalid time source specification: " + sourceStr);
            }

            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 FormatException("Invalid time components and separator: " + timeComponents + timeSeparator);
                }
            }

            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 FormatException("Invalid number base: " + numberBase);
                }
                else if (numberBase == 28)
                {
                    data.Alphabet = base28Alphabet;
                }
                else
                {
                    data.Alphabet = new char[numberBase];
                    Array.Copy(base36Alphabet, data.Alphabet, numberBase);
                }
            }
            return(data);
        }