使用TimeZoneInfo:
static void Main() { TimeZoneInfo wa = TimeZoneInfo.FindSystemTimeZoneById ("W. Australia Standard Time"); Console.WriteLine (wa.Id); // W. Australia Standard Time Console.WriteLine (wa.DisplayName); // (GMT+08:00) Perth Console.WriteLine (wa.BaseUtcOffset); // 08:00:00 Console.WriteLine (wa.SupportsDaylightSavingTime); // True foreach (TimeZoneInfo.AdjustmentRule rule in wa.GetAdjustmentRules()) { Console.WriteLine ("Rule: applies from " + rule.DateStart + " to " + rule.DateEnd); Console.WriteLine (" Delta: " + rule.DaylightDelta); Console.WriteLine (" Start: " + FormatTransitionTime (rule.DaylightTransitionStart, false)); Console.WriteLine (" End: " + FormatTransitionTime (rule.DaylightTransitionEnd, true)); Console.WriteLine(); } } static string FormatTransitionTime (TimeZoneInfo.TransitionTime tt, bool endTime) { if (endTime && tt.IsFixedDateRule && tt.Day == 1 && tt.Month == 1 && tt.TimeOfDay == DateTime.MinValue) return "-"; string s; if (tt.IsFixedDateRule) s = tt.Day.ToString(); else s = "The " + "first second third fourth last".Split() [tt.Week - 1] + " " + tt.DayOfWeek + " in"; return s + " " + DateTimeFormatInfo.CurrentInfo.MonthNames [tt.Month-1] + " at " + tt.TimeOfDay.TimeOfDay; }
DateTime和daylight保存:
DaylightTime changes = TimeZone.CurrentTimeZone.GetDaylightChanges (2008); TimeSpan halfDelta = new TimeSpan (changes.Delta.Ticks / 2); DateTime utc1 = changes.End.ToUniversalTime() - halfDelta; DateTime utc2 = utc1 - changes.Delta; // Converting these variables to local times demonstrates why you should use // UTC and not local time if your code relies on time moving forward: DateTime loc1 = utc1.ToLocalTime(); // (Pacific Standard Time) DateTime loc2 = utc2.ToLocalTime(); Console.WriteLine (loc1); // 2/11/2008 1:30:00 AM Console.WriteLine (loc2); // 2/11/2008 1:30:00 AM Console.WriteLine (loc1 == loc2); // True Console.Write (loc1.ToString ("o")); // 2008-11-02T02:30:00.0000000-08:00 Console.Write (loc2.ToString ("o")); // 2008-11-02T02:30:00.0000000-07:00 Console.WriteLine (loc1.ToUniversalTime() == utc1); // True Console.WriteLine (loc2.ToUniversalTime() == utc2); // True
写一个自定义格式provider:
public class WordyFormatProvider : IFormatProvider, ICustomFormatter { static readonly string[] _numberWords = "zero one two three four five six seven eight nine minus point".Split(); IFormatProvider _parent; // Allows consumers to chain format providers public WordyFormatProvider() : this (CultureInfo.CurrentCulture) { } public WordyFormatProvider (IFormatProvider parent) { _parent = parent; } public object GetFormat (Type formatType) { if (formatType == typeof (ICustomFormatter)) return this; return null; } public string Format (string format, object arg, IFormatProvider prov) { // If it's not our format string, defer to the parent provider: if (arg == null || format != "W") return string.Format (_parent, "{0:" + format + "}", arg); StringBuilder result = new StringBuilder(); string digitList = string.Format (CultureInfo.InvariantCulture, "{0}", arg); foreach (char digit in digitList) { int i = "0123456789-.".IndexOf (digit); if (i == -1) continue; if (result.Length > 0) result.Append (' '); result.Append (_numberWords[i]); } return result.ToString(); } }
重载相等语义:
public struct Area : IEquatable <Area> { public readonly int Measure1; public readonly int Measure2; public Area (int m1, int m2) { Measure1 = m1; Measure2 = m2; } public override bool Equals (object other) { if (!(other is Area)) return false; return Equals ((Area) other); // Calls method below } public bool Equals (Area other) // Implements IEquatable<Area> { return Measure1 == other.Measure1 && Measure2 == other.Measure2 || Measure1 == other.Measure2 && Measure2 == other.Measure1; } public override int GetHashCode() { if (Measure1 > Measure2) return Measure1 * 37 + Measure2; // 37 = a prime number else return Measure2 * 37 + Measure1; } public static bool operator == (Area a1, Area a2) { return a1.Equals (a2); } public static bool operator != (Area a1, Area a2) { return !a1.Equals (a2); } }
实现IComparable接口:
public struct Note : IComparable<Note>, IEquatable<Note>, IComparable { int _semitonesFromA; public Note (int semitonesFromA) { _semitonesFromA = semitonesFromA; } public int CompareTo (Note other) // Generic IComparable<T> { if (Equals (other)) return 0; // Fail-safe check return _semitonesFromA.CompareTo (other._semitonesFromA); } int IComparable.CompareTo (object other) // Nongeneric IComparable { if (!(other is Note)) throw new InvalidOperationException ("CompareTo: Not a note"); return CompareTo ((Note) other); } public static bool operator < (Note n1, Note n2) { return n1.CompareTo (n2) < 0; } public static bool operator > (Note n1, Note n2) { return n1.CompareTo (n2) > 0; } public bool Equals (Note other) // for IEquatable<Note> { return _semitonesFromA == other._semitonesFromA; } public override bool Equals (object other) { if (!(other is Note)) return false; return Equals ((Note) other); } public override int GetHashCode() { return _semitonesFromA.GetHashCode(); } public static bool operator == (Note n1, Note n2) { return n1.Equals (n2); } public static bool operator != (Note n1, Note n2) { return !(n1 == n2); } }