Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Globalization / TimeSpanFormat.cs / 1305376 / TimeSpanFormat.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// [....]
//
namespace System.Globalization {
using System.Text;
using System;
using System.Diagnostics.Contracts;
using System.Globalization;
internal static class TimeSpanFormat {
[System.Security.SecuritySafeCritical] // auto-generated
private static String IntToString(int n, int digits) {
return ParseNumbers.IntToString(n, 10, digits, '0', 0);
}
internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(false /*isNegative*/);
internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(true /*isNegative*/);
internal enum Pattern {
None = 0,
Minimum = 1,
Full = 2,
}
//
// Format
//
// Actions: Main method called from TimeSpan.ToString
//
internal static String Format(TimeSpan value, String format, IFormatProvider formatProvider) {
if (format == null || format.Length == 0)
format = "c";
// standard formats
if (format.Length == 1) {
char f = format[0];
if (f == 'c' || f == 't' || f == 'T')
return FormatStandard(value, true, format, Pattern.Minimum);
if (f == 'g' || f == 'G') {
Pattern pattern;
DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(formatProvider);
if (value._ticks < 0)
format = dtfi.FullTimeSpanNegativePattern;
else
format = dtfi.FullTimeSpanPositivePattern;
if (f == 'g')
pattern = Pattern.Minimum;
else
pattern = Pattern.Full;
return FormatStandard(value, false, format, pattern);
}
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
}
return FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider));
}
//
// FormatStandard
//
// Actions: Format the TimeSpan instance using the specified format.
//
private static String FormatStandard(TimeSpan value, bool isInvariant, String format, Pattern pattern) {
StringBuilder sb = new StringBuilder();
int day = (int)(value._ticks / TimeSpan.TicksPerDay);
long time = value._ticks % TimeSpan.TicksPerDay;
if (value._ticks < 0) {
day = -day;
time = -time;
}
int hours = (int)(time / TimeSpan.TicksPerHour % 24);
int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
int fraction = (int)(time % TimeSpan.TicksPerSecond);
FormatLiterals literal;
if (isInvariant) {
if (value._ticks < 0)
literal = NegativeInvariantFormatLiterals;
else
literal = PositiveInvariantFormatLiterals;
}
else {
literal = new FormatLiterals();
literal.Init(format, pattern == Pattern.Full);
}
if (fraction != 0) { // truncate the partial second to the specified length
fraction = (int)((long)fraction / (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - literal.ff));
}
// Pattern.Full: [-]dd.hh:mm:ss.fffffff
// Pattern.Minimum: [-][d.]hh:mm:ss[.fffffff]
sb.Append(literal.Start); // [-]
if (pattern == Pattern.Full || day != 0) { //
sb.Append(day); // [dd]
sb.Append(literal.DayHourSep); // [.]
} //
sb.Append(IntToString(hours, literal.hh)); // hh
sb.Append(literal.HourMinuteSep); // :
sb.Append(IntToString(minutes, literal.mm)); // mm
sb.Append(literal.MinuteSecondSep); // :
sb.Append(IntToString(seconds, literal.ss)); // ss
if (!isInvariant && pattern == Pattern.Minimum) {
int effectiveDigits = literal.ff;
while (effectiveDigits > 0) {
if (fraction % 10 == 0) {
fraction = fraction / 10;
effectiveDigits--;
}
else {
break;
}
}
if (effectiveDigits > 0) {
sb.Append(literal.SecondFractionSep); // [.FFFFFFF]
sb.Append((fraction).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
}
}
else if (pattern == Pattern.Full || fraction != 0) {
sb.Append(literal.SecondFractionSep); // [.]
sb.Append(IntToString(fraction, literal.ff)); // [fffffff]
} //
sb.Append(literal.End); //
return sb.ToString();
}
//
// FormatCustomized
//
// Actions: Format the TimeSpan instance using the specified format.
//
internal static String FormatCustomized(TimeSpan value, String format, DateTimeFormatInfo dtfi) {
Contract.Assert(dtfi != null, "dtfi == null");
int day = (int)(value._ticks / TimeSpan.TicksPerDay);
long time = value._ticks % TimeSpan.TicksPerDay;
if (value._ticks < 0) {
day = -day;
time = -time;
}
int hours = (int)(time / TimeSpan.TicksPerHour % 24);
int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
int fraction = (int)(time % TimeSpan.TicksPerSecond);
long tmp = 0;
int i = 0;
int tokenLen;
StringBuilder result = new StringBuilder();
while (i < format.Length) {
char ch = format[i];
int nextChar;
switch (ch) {
case 'h':
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
DateTimeFormat.FormatDigits(result, hours, tokenLen);
break;
case 'm':
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
DateTimeFormat.FormatDigits(result, minutes, tokenLen);
break;
case 's':
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
DateTimeFormat.FormatDigits(result, seconds, tokenLen);
break;
case 'f':
//
// The fraction of a second in single-digit precision. The remaining digits are truncated.
//
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
tmp = (long)fraction;
tmp /= (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture));
break;
case 'F':
//
// Displays the most significant digit of the seconds fraction. Nothing is displayed if the digit is zero.
//
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
tmp = (long)fraction;
tmp /= (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
int effectiveDigits = tokenLen;
while (effectiveDigits > 0) {
if (tmp % 10 == 0) {
tmp = tmp / 10;
effectiveDigits--;
}
else {
break;
}
}
if (effectiveDigits > 0) {
result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
}
break;
case 'd':
//
// tokenLen == 1 : Day as digits with no leading zero.
// tokenLen == 2+: Day as digits with leading zero for single-digit days.
//
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 8)
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
DateTimeFormat.FormatDigits(result, day, tokenLen, true);
break;
case '\'':
case '\"':
StringBuilder enquotedString = new StringBuilder();
tokenLen = DateTimeFormat.ParseQuoteString(format, i, enquotedString);
result.Append(enquotedString);
break;
case '%':
// Optional format character.
// For example, format string "%d" will print day
// Most of the cases, "%" can be ignored.
nextChar = DateTimeFormat.ParseNextChar(format, i);
// nextChar will be -1 if we already reach the end of the format string.
// Besides, we will not allow "%%" appear in the pattern.
if (nextChar >= 0 && nextChar != (int)'%') {
result.Append(TimeSpanFormat.FormatCustomized(value, ((char)nextChar).ToString(), dtfi));
tokenLen = 2;
}
else
{
//
// This means that '%' is at the end of the format string or
// "%%" appears in the format string.
//
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
}
break;
case '\\':
// Escaped character. Can be used to insert character into the format string.
// For example, "\d" will insert the character 'd' into the string.
//
nextChar = DateTimeFormat.ParseNextChar(format, i);
if (nextChar >= 0)
{
result.Append(((char)nextChar));
tokenLen = 2;
}
else
{
//
// This means that '\' is at the end of the formatting string.
//
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
}
break;
default:
throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
}
i += tokenLen;
}
return (result.ToString());
}
internal struct FormatLiterals {
internal String Start {
get {
return literals[0];
}
}
internal String DayHourSep {
get {
return literals[1];
}
}
internal String HourMinuteSep {
get {
return literals[2];
}
}
internal String MinuteSecondSep {
get {
return literals[3];
}
}
internal String SecondFractionSep {
get {
return literals[4];
}
}
internal String End {
get {
return literals[5];
}
}
internal String AppCompatLiteral;
internal int dd;
internal int hh;
internal int mm;
internal int ss;
internal int ff;
private String[] literals;
/* factory method for static invariant FormatLiterals */
internal static FormatLiterals InitInvariant(bool isNegative) {
FormatLiterals x = new FormatLiterals();
x.literals = new String[6];
x.literals[0] = isNegative ? "-" : String.Empty;
x.literals[1] = ".";
x.literals[2] = ":";
x.literals[3] = ":";
x.literals[4] = ".";
x.literals[5] = String.Empty;
x.AppCompatLiteral = ":."; // MinuteSecondSep+SecondFractionSep;
x.dd = 2;
x.hh = 2;
x.mm = 2;
x.ss = 2;
x.ff = DateTimeFormat.MaxSecondsFractionDigits;
return x;
}
// For the "v1" TimeSpan localized patterns, the data is simply literal field separators with
// the constants guaranteed to include DHMSF ordered greatest to least significant.
// Once the data becomes more complex than this we will need to write a proper tokenizer for
// parsing and formatting
internal void Init(String format, bool useInvariantFieldLengths) {
literals = new String[6];
for (int i = 0; i < literals.Length; i++)
literals[i] = String.Empty;
dd = 0;
hh = 0;
mm = 0;
ss = 0;
ff = 0;
StringBuilder sb = new StringBuilder();
bool inQuote = false;
char quote = '\'';
int field = 0;
for (int i = 0; i < format.Length; i++) {
switch (format[i]) {
case '\'':
case '\"':
if (inQuote && (quote == format[i])) {
/* we were in a quote and found a matching exit quote, so we are outside a quote now */
Contract.Assert(field >= 0 && field <= 5, "field >= 0 && field <= 5");
if (field >= 0 && field <= 5) {
literals[field] = sb.ToString();
sb.Length = 0;
inQuote = false;
}
else {
return; // how did we get here?
}
}
else if (!inQuote) {
/* we are at the start of a new quote block */
quote = format[i];
inQuote = true;
}
else {
/* we were in a quote and saw the other type of quote character, so we are still in a quote */
}
break;
case '%':
Contract.Assert(false, "Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
goto default;
case '\\':
if (!inQuote) {
i++; /* skip next character that is escaped by this backslash or percent sign */
break;
}
goto default;
case 'd':
if (!inQuote) {
Contract.Assert((field == 0 && sb.Length == 0) || field == 1,
"field == 0 || field == 1, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
field = 1; // DayHourSep
dd++;
}
break;
case 'h':
if (!inQuote) {
Contract.Assert((field == 1 && sb.Length == 0) || field == 2,
"field == 1 || field == 2, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
field = 2; // HourMinuteSep
hh++;
}
break;
case 'm':
if (!inQuote) {
Contract.Assert((field == 2 && sb.Length == 0) || field == 3,
"field == 2 || field == 3, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
field = 3; // MinuteSecondSep
mm++;
}
break;
case 's':
if (!inQuote) {
Contract.Assert((field == 3 && sb.Length == 0) || field == 4,
"field == 3 || field == 4, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
field = 4; // SecondFractionSep
ss++;
}
break;
case 'f':
case 'F':
if (!inQuote) {
Contract.Assert((field == 4 && sb.Length == 0) || field == 5,
"field == 4 || field == 5, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
field = 5; // End
ff++;
}
break;
default:
sb.Append(format[i]);
break;
}
}
Contract.Assert(field == 5);
AppCompatLiteral = MinuteSecondSep + SecondFractionSep;
Contract.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
Contract.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
Contract.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
Contract.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
Contract.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
if (useInvariantFieldLengths) {
dd = 2;
hh = 2;
mm = 2;
ss = 2;
ff = DateTimeFormat.MaxSecondsFractionDigits;
}
else {
if (dd < 1 || dd > 2) dd = 2; // The DTFI property has a problem. let's try to make the best of the situation.
if (hh < 1 || hh > 2) hh = 2;
if (mm < 1 || mm > 2) mm = 2;
if (ss < 1 || ss > 2) ss = 2;
if (ff < 1 || ff > 7) ff = 7;
}
}
} //end of struct FormatLiterals
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ScrollableControl.cs
- RSAPKCS1KeyExchangeFormatter.cs
- CombinedGeometry.cs
- WebPartConnectionsConnectVerb.cs
- DocumentReference.cs
- LinkedList.cs
- KeyGestureValueSerializer.cs
- ZipIOLocalFileDataDescriptor.cs
- FormViewRow.cs
- FastPropertyAccessor.cs
- TextElementCollection.cs
- ObjectTag.cs
- ModelServiceImpl.cs
- COM2FontConverter.cs
- Policy.cs
- ApplicationException.cs
- FeatureManager.cs
- BrowserCapabilitiesCompiler.cs
- MissingMemberException.cs
- JulianCalendar.cs
- Boolean.cs
- Matrix3DStack.cs
- FrameworkElementAutomationPeer.cs
- RunClient.cs
- SiteMapDataSource.cs
- FunctionDetailsReader.cs
- WebPart.cs
- ToolboxItemCollection.cs
- WebPartZone.cs
- FreezableDefaultValueFactory.cs
- RelationshipManager.cs
- HttpHostedTransportConfiguration.cs
- CompositeControlDesigner.cs
- SimpleTextLine.cs
- HWStack.cs
- FileSystemEventArgs.cs
- WindowsListViewSubItem.cs
- CustomAttribute.cs
- Trace.cs
- ConfigurationLocation.cs
- SqlNodeAnnotation.cs
- translator.cs
- AnimatedTypeHelpers.cs
- BoundPropertyEntry.cs
- HttpServerVarsCollection.cs
- AutoResizedEvent.cs
- ThreadExceptionEvent.cs
- AuthenticationSection.cs
- OperationAbortedException.cs
- SuppressIldasmAttribute.cs
- ObjectViewEntityCollectionData.cs
- SamlSubject.cs
- ErrorTableItemStyle.cs
- StorageScalarPropertyMapping.cs
- CornerRadius.cs
- SendDesigner.xaml.cs
- AxisAngleRotation3D.cs
- DaylightTime.cs
- SqlInternalConnectionTds.cs
- InstanceStoreQueryResult.cs
- XmlQueryType.cs
- PrimitiveXmlSerializers.cs
- Constants.cs
- compensatingcollection.cs
- HtmlTableCellCollection.cs
- HttpResponse.cs
- AttributeTable.cs
- XmlCollation.cs
- OleDbTransaction.cs
- WindowsTooltip.cs
- SafeNativeMethods.cs
- GestureRecognizer.cs
- XmlSchemaSequence.cs
- ServicePointManagerElement.cs
- BinaryFormatter.cs
- TemplateField.cs
- Console.cs
- GenericArgumentsUpdater.cs
- XmlNodeChangedEventArgs.cs
- WeakReadOnlyCollection.cs
- Matrix3DValueSerializer.cs
- XmlSignificantWhitespace.cs
- XDeferredAxisSource.cs
- AcceptorSessionSymmetricMessageSecurityProtocol.cs
- TypeConverterAttribute.cs
- Propagator.JoinPropagator.JoinPredicateVisitor.cs
- CodeTypeReferenceExpression.cs
- HostVisual.cs
- SQLSingleStorage.cs
- Utils.cs
- CreateUserWizardStep.cs
- UriScheme.cs
- SchemaCollectionCompiler.cs
- InvalidChannelBindingException.cs
- PropertyChangedEventManager.cs
- WindowInteractionStateTracker.cs
- WFItemsToSpacerVisibility.cs
- DateTimeConverter2.cs
- DataRelationCollection.cs
- TextAnchor.cs