2014-10-29 33 views

回答

2

我將根據其格式解析它:http://www.ibm.com/developerworks/aix/library/au-aix-posix/

也許你也可以考慮:http://nodatime.org/ - 我目前不知道他們是否支持此功能。

+0

解析POSIX以獲得'standard.Offset','daylight.Offset','toDaylight.Date'和'toStandard.Date',然後您需要遍歷可用的'TimeZoneInfo'來查找匹配項。如果沒有匹配,則再次重複忽略這兩個日期。如果你得到多個比賽,那麼你需要選擇一個。如果你沒有匹配,那麼它可能是一個常識字符串而不是'POSIX'字符串。 :) – 2015-02-20 01:07:22

0

下面的代碼應該做的伎倆。

請記住,雖然這會給你一個有效的TimeZoneInfo對象,它確實將而不是映射到現有的Windows時區。您可以使用各種轉換功能,例如TimeZoneInfo.ConvertTime,但不要指望它神奇地知道PST8PDT應與"Pacific Standard Time"對齊。

public static TimeZoneInfo PosixToTzi(string posixTz) 
{ 
    var parts = posixTz.Split(','); 
    var zoneparts = Regex.Split(parts[0], @"([0-9\+\-\.]+)"); 

    double baseOffsetHours; 
    if (zoneparts.Length > 1) 
    { 
     if (!Double.TryParse(zoneparts[1], out baseOffsetHours)) 
      throw new FormatException(); 
    } 
    else 
    { 
     // recognize RFC822 time zone abbreviations 
     switch (zoneparts[0].ToUpper()) 
     { 
      case "UT": 
      case "UTC": 
      case "GMT": 
       baseOffsetHours = 0; 
       break; 
      case "EDT": 
       baseOffsetHours = 4; 
       break; 
      case "EST": 
      case "CDT": 
       baseOffsetHours = 5; 
       break; 
      case "CST": 
      case "MDT": 
       baseOffsetHours = 6; 
       break; 
      case "MST": 
      case "PDT": 
       baseOffsetHours = 7; 
       break; 
      case "PST": 
       baseOffsetHours = 8; 
       break; 
      default: 
       throw new FormatException(); 
     } 
    } 

    double dstOffsetHours = baseOffsetHours - 1; 
    if (zoneparts.Length == 4) 
    { 
     if (!Double.TryParse(zoneparts[3], out dstOffsetHours)) 
      throw new FormatException(); 
    } 

    var baseOffset = TimeSpan.FromHours(-baseOffsetHours); 
    var dstDelta = TimeSpan.FromHours(baseOffsetHours - dstOffsetHours); 

    var rules = new List<TimeZoneInfo.AdjustmentRule>(); 
    if (parts.Length == 3) 
    { 
     var rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
      DateTime.MinValue.Date, DateTime.MaxValue.Date, dstDelta, 
      ParsePosixTransition(parts[1]), ParsePosixTransition(parts[2])); 

     rules.Add(rule); 
    } 

    return TimeZoneInfo.CreateCustomTimeZone(posixTz, baseOffset, parts[0], zoneparts[0], 
     zoneparts[zoneparts.Length == 3 ? 2 : 0], rules.ToArray()); 
} 

private static TimeZoneInfo.TransitionTime ParsePosixTransition(string transition) 
{ 
    var parts = transition.Split('/'); 
    if (parts.Length > 2) 
      throw new FormatException(); 

    double hours = 0; 
    if (parts.Length == 2) 
    { 
     if (!Double.TryParse(parts[1], out hours)) 
      throw new FormatException(); 
    } 
    var time = DateTime.MinValue.AddHours(hours); 

    if (transition.StartsWith("M", StringComparison.OrdinalIgnoreCase)) 
    { 
     var dateParts = parts[0].Substring(1).Split('.'); 
     if (dateParts.Length > 3) 
      throw new FormatException(); 

     int month; 
     if (!Int32.TryParse(dateParts[0], out month)) 
      throw new FormatException(); 

     int week; 
     if (!Int32.TryParse(dateParts[1], out week)) 
      throw new FormatException(); 

     int dow; 
     if (!Int32.TryParse(dateParts[2], out dow)) 
      throw new FormatException(); 

     return TimeZoneInfo.TransitionTime.CreateFloatingDateRule(time, month, week, (DayOfWeek) dow); 
    } 

    if (transition.StartsWith("J", StringComparison.OrdinalIgnoreCase)) 
    { 
     int dayNum; 
     if (!Int32.TryParse(parts[0].Substring(1), out dayNum)) 
      throw new FormatException(); 
     var date = DateTime.MinValue.AddDays(dayNum); 

     return TimeZoneInfo.TransitionTime.CreateFixedDateRule(time, date.Month, date.Day); 
    } 

    throw new FormatException(); 
} 
2

根據這篇文章:http://www.ibm.com/developerworks/aix/library/au-aix-posix/一POSIX時間等 「CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00」 有下列規格:

  • CST6CDT是時區
  • CST的名稱使用縮寫時DST是關閉
  • 6小時是從GMT的時差
  • CDT是所使用的縮寫當DST是
  • ,M3是第三個月
  • 0.2是一天在本月
  • 0.0是星期日
  • /2第二次出現:00:00是時間
  • ,M11是第十一一個月
  • .1一天在一個月
  • 0.0是星期天
  • /2中第一次出現:00:00的時間

,日期在Mm.n.d格式,其中:

  • 毫米(1-12)12個月
  • N(1-5)1的第一個星期和5的最後一個星期在一個月
  • d(0- 6)0爲週日和6日

好了,基於這些信息,並可能在的TimeZoneInfo類中找到的調整規則,你可以使用此代碼來進行轉換:

public static TimeZoneInfo ConvertPosixToTimeZoneInfo(string posix) 
    { 
     string[] tokens = posix.Split(','); 
     tokens[0] = tokens[0].Replace("/", "."); 
     var match = Regex.Match(tokens[0], @"[-+]?[0-9]*\.?[0-9]+").Value; 
     var ticks = (long)(decimal.Parse(match, CultureInfo.InvariantCulture) * 60) * 600000000; 
     var baseOffset = new TimeSpan(ticks); 

     var systemTimeZones = TimeZoneInfo.GetSystemTimeZones().Where(t => t.BaseUtcOffset == baseOffset).ToList(); 

     var startRuleTokens = tokens[1].TrimStart('M').Split('/'); 
     var startDateRuleTokens = startRuleTokens[0].Split('.'); 
     var startTimeRuleTokens = startRuleTokens[1].Split(':'); 

     var endRuleTokens = tokens[2].TrimStart('M').Split('/'); 
     var endDateRuleTokens = endRuleTokens[0].Split('.'); 
     var endTimeRuleTokens = endRuleTokens[1].Split(':'); 

     int? targetIndex = null; 
     for (int i = 0; i < systemTimeZones.Count; i++) 
     { 
      var adjustmentRules = systemTimeZones[i].GetAdjustmentRules(); 
      foreach (var rule in adjustmentRules) 
      { 
       if (rule.DaylightTransitionStart.Month == int.Parse(startDateRuleTokens[0]) && 
        rule.DaylightTransitionStart.Week == int.Parse(startDateRuleTokens[1]) && 
        rule.DaylightTransitionStart.DayOfWeek == (DayOfWeek)int.Parse(startDateRuleTokens[2]) && 
        rule.DaylightTransitionStart.TimeOfDay.Hour == int.Parse(startTimeRuleTokens[0]) && 
        rule.DaylightTransitionStart.TimeOfDay.Minute == int.Parse(startTimeRuleTokens[1]) && 
        rule.DaylightTransitionStart.TimeOfDay.Second == int.Parse(startTimeRuleTokens[2]) && 

        rule.DaylightTransitionEnd.Month == int.Parse(endDateRuleTokens[0]) && 
        rule.DaylightTransitionEnd.Week == int.Parse(endDateRuleTokens[1]) && 
        rule.DaylightTransitionEnd.DayOfWeek == (DayOfWeek)int.Parse(endDateRuleTokens[2]) && 
        rule.DaylightTransitionEnd.TimeOfDay.Hour == int.Parse(endTimeRuleTokens[0]) && 
        rule.DaylightTransitionEnd.TimeOfDay.Minute == int.Parse(endTimeRuleTokens[1]) && 
        rule.DaylightTransitionEnd.TimeOfDay.Second == int.Parse(endTimeRuleTokens[2])) 
       { 
        targetIndex = i; 
        break; 
       } 
      } 
     } 

     if (targetIndex.HasValue) 
      return systemTimeZones[targetIndex.Value]; 
     return null; 
    }