public DateTimeParts(DateParts dateParts, TimeParts timeParts) {
     _date = dateParts;
     _time = timeParts;
 }
 public DateTimeParts(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind, TimeSpan offset) {
     _date = new DateParts(year, month, day);
     _time = new TimeParts(hour, minute, second, millisecond, kind, offset);
 }
 protected virtual void GetTimeFormatValues(TimeParts parts, out bool isPm, out int hour12, out string amPm, out string amPmShort, out string timeZone, out string offsetSign, out int offsetHours, out int offsetMinutes, out string fraction1Zero, out string fraction2Zero, out string fraction3Zero, out string fraction1Digit, out string fraction2Digit, out string fraction3Digit) {
     hour12 = ConvertToHour12(parts.Hour, out isPm);
     amPm = _dateTimeFormatProvider.AmPmDesignators[isPm ? 1 : 0];
     amPmShort = String.IsNullOrEmpty(amPm) ? "" : amPm[0].ToString();
     offsetSign = parts.Offset.GetValueOrDefault() < TimeSpan.Zero ? "-" : "+";
     offsetHours = Math.Abs(parts.Offset.GetValueOrDefault().Hours);
     offsetMinutes = Math.Abs(parts.Offset.GetValueOrDefault().Minutes);
     timeZone = "";
     switch (parts.Kind) {
         case DateTimeKind.Utc:
             timeZone = "Z";
             break;
         case DateTimeKind.Local:
             timeZone = String.Format("{0}{1:00}:{2:00}", offsetSign, offsetHours, offsetMinutes);
             break;
     }
     fraction1Zero = (((decimal)parts.Millisecond) / 1000).ToString("0.0", CultureInfo.InvariantCulture).Substring(2);
     fraction2Zero = (((decimal)parts.Millisecond) / 1000).ToString("0.00", CultureInfo.InvariantCulture).Substring(2);
     fraction3Zero = (((decimal)parts.Millisecond) / 1000).ToString("0.000", CultureInfo.InvariantCulture).Substring(2);
     var fraction1 = (((decimal)parts.Millisecond) / 1000).ToString("0.#", CultureInfo.InvariantCulture);
     var fraction2 = (((decimal)parts.Millisecond) / 1000).ToString("0.##", CultureInfo.InvariantCulture);
     var fraction3 = (((decimal)parts.Millisecond) / 1000).ToString("0.###", CultureInfo.InvariantCulture);
     fraction1Digit = fraction1.Length >= 2 ? fraction1.Substring(2) : "";
     fraction2Digit = fraction2.Length >= 2 ? fraction2.Substring(2) : "";
     fraction3Digit = fraction3.Length >= 2 ? fraction3.Substring(2) : "";
 }
        public virtual string FormatTime(TimeParts parts, string format) {
            var replacements = GetTimeFormatReplacements();
            var formatString = ConvertToFormatString(format, replacements);

            bool isPm;
            int hour12, offsetHours, offsetMinutes;
            string amPm, amPmShort, timeZone, offsetSign, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit;
            GetTimeFormatValues(parts, out isPm, out hour12, out amPm, out amPmShort, out timeZone, out offsetSign, out offsetHours, out offsetMinutes, out fraction1Zero, out fraction2Zero, out fraction3Zero, out fraction1Digit, out fraction2Digit, out fraction3Digit);

            return String.Format(formatString, null, null, null, null, null, null, null, null, null, null, null, null, parts.Hour, hour12, parts.Minute, parts.Second, fraction1Zero, fraction2Zero, fraction3Zero, fraction1Digit, fraction2Digit, fraction3Digit, amPm, amPmShort, timeZone, offsetSign, offsetHours, offsetMinutes);
        }
 public virtual string FormatTime(TimeParts parts) {
     return FormatTime(parts, _dateTimeFormatProvider.LongTimeFormat);
 }
        public void FormatTimeTest01() {
            var allCases = new ConcurrentBag<string>();
            var failedCases = new ConcurrentDictionary<string, Exception>();
            var maxFailedCases = 0;

            var options = new ParallelOptions();
            if (Debugger.IsAttached) {
                options.MaxDegreeOfParallelism = 1;
            }

            var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
            Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
                var container = TestHelpers.InitializeContainer(culture.Name, null, TimeZoneInfo.Utc);
                var formats = container.Resolve<IDateTimeFormatProvider>();
                var target = container.Resolve<IDateFormatter>();

                foreach (var timeFormat in formats.AllTimeFormats) { // All time formats supported by the culture.
                    for (var hour = 0; hour <= 23; hour++) { // All hours in the day.

                        DateTime date = new DateTime(1998, 1, 1, hour, 30, 30, 678);
                        TimeParts timeParts = new TimeParts(hour, 30, 30, 678, DateTimeKind.Unspecified, offset: TimeSpan.Zero);

                        var caseKey = String.Format("{0}___{1}___{2}", culture.Name, timeFormat, timeParts);
                        allCases.Add(caseKey);
                        //Debug.WriteLine(String.Format("{0} cases tested so far. Testing case {1}...", allCases.Count, caseKey));

                        try {
                            var result = target.FormatTime(timeParts, timeFormat);
                            var expected = date.ToString(timeFormat, culture);
                            Assert.AreEqual(expected, result);
                        }
                        catch (Exception ex) {
                            failedCases.TryAdd(caseKey, ex);
                        }
                    }
                }
            });

            if (failedCases.Count > maxFailedCases) {
                throw new AggregateException(String.Format("Format tests failed for {0} of {1} cases. Expected {2} failed cases or less.", failedCases.Count, allCases.Count, maxFailedCases), failedCases.Values);
            }
        }