2010-11-22 7 views
1

Je travaille sur une application héritée dans .NET 2.0 et je veux convertir l'heure de l'heure locale (qui se trouve être UTC + 1) à l'heure au Brésil (c'est "E. South America Standard Time "comme Windows l'appelle" et retour.C# 2.0 fuseau horaire spécifique

Je mets ensemble ce code que je suis venu avec pour faire la conversion:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 
using Microsoft.Win32; 

namespace timezone 
{ 
class Program 
{ 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)] 
    private static extern int SystemTimeToTzSpecificLocalTime(ref 
    TIME_ZONE_INFORMATION lpTimeZone, ref SYSTEMTIME lpUniversalTIme, out 
    SYSTEMTIME lpLocalTime); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)] 
    private static extern int TzSpecificLocalTimeToSystemTime(ref 
    TIME_ZONE_INFORMATION lpTimeZone, ref SYSTEMTIME lpLocalTime, out SYSTEMTIME 
    lpUniversalTIme); 

    [DllImport("kernel32.dll")] 
    private static extern void GetSystemTime(out SYSTEMTIME lpSystemTime); 

    [StructLayout(LayoutKind.Sequential)] 
    private struct SYSTEMTIME 
    { 
    public ushort wYear; 
    public ushort wMonth; 
    public ushort wDayOfWeek; 
    public ushort wDay; 
    public ushort wHour; 
    public ushort wMinute; 
    public ushort wSecond; 
    public ushort wMilliseconds; 
    } 

    //Registry time zone format. See KB article Q115231 
    [StructLayout(LayoutKind.Sequential)] 
    private struct REG_TIME_ZONE_INFORMATION 
    { 
    public int Bias; 
    public int StandardBias; 
    public int DaylightBias; 
    public SYSTEMTIME StandardDate; 
    public SYSTEMTIME DaylightDate; 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    private struct TIME_ZONE_INFORMATION 
    { 
    public int Bias; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string StandardName; 
    public SYSTEMTIME StandardDate; 
    public int StandardBias; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string DaylightName; 
    public SYSTEMTIME DaylightDate; 
    public int DaylightBias; 
    } 

    private static List<TIME_ZONE_INFORMATION> GetTimeZones() 
    { 
    List<TIME_ZONE_INFORMATION> list = new List<TIME_ZONE_INFORMATION>(); 
    RegistryKey key = 
    Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"); 
    if (key == null) 
    return list; 

    string[] subKeyNames = key.GetSubKeyNames(); 
    foreach (string subKeyName in subKeyNames) 
    { 
    RegistryKey subKey = key.OpenSubKey(subKeyName); 
    if (subKey != null) 
    { 
    object value = subKey.GetValue("TZI"); 
    if (value != null) 
    { 
     int length = 
     Marshal.SizeOf(typeof(REG_TIME_ZONE_INFORMATION)); 
     IntPtr p = Marshal.AllocHGlobal(length); 
     Marshal.Copy((byte[])value, 0, p, length); 
     REG_TIME_ZONE_INFORMATION rtzi = 
     (REG_TIME_ZONE_INFORMATION)Marshal.PtrToStructure(p, 
     typeof(REG_TIME_ZONE_INFORMATION)); 
     Marshal.FreeHGlobal(p); 

     TIME_ZONE_INFORMATION tzi = new TIME_ZONE_INFORMATION(); 
     tzi.Bias = rtzi.Bias; 
     tzi.DaylightBias = rtzi.DaylightBias; 
     tzi.StandardBias = rtzi.StandardBias; 
     tzi.DaylightDate = rtzi.DaylightDate; 
     tzi.StandardDate = rtzi.StandardDate; 
     tzi.DaylightName = (string)subKey.GetValue("Dlt", ""); 
     tzi.StandardName = (string)subKey.GetValue("Std", ""); 
     list.Add(tzi); 
    } 
    subKey.Close(); 
    } 
    } 
    key.Close(); 
    return list; 
    } 

    static void Main(string[] args) 
    { 
    foreach (TIME_ZONE_INFORMATION tzi in GetTimeZones()) 
    { 
    if ("E. South America Standard Time" == tzi.StandardName) 
    { 
    Console.WriteLine("local time: " + DateTime.Now); 
    Console.WriteLine("name: {0} st bias:{1} daylight date:{2}-{3}-{4}, bias:{5}", tzi.StandardName, tzi.DaylightBias, tzi.DaylightDate.wDay, tzi.DaylightDate.wMonth, tzi.DaylightDate.wYear, tzi.Bias); 
    TIME_ZONE_INFORMATION tzi2 = tzi; //local copy so that i can pass it as a ref 
    SYSTEMTIME braziltime = new SYSTEMTIME(); 
    SYSTEMTIME localtime = new SYSTEMTIME(); 
    GetSystemTime(out localtime); 
    SystemTimeToTzSpecificLocalTime(ref tzi2, ref localtime, out braziltime); 
    Console.WriteLine("{0}:{1}", braziltime.wHour, braziltime.wMinute); 
    Console.WriteLine("{0}-{1}-{2} {3}:{4}:{5}", braziltime.wYear, braziltime.wMonth, braziltime.wDay, braziltime.wHour, braziltime.wMinute, braziltime.wSecond); 
    DateTime dt = DateTime.Now; 
    braziltime.wYear = (ushort)dt.Year; 
    braziltime.wMonth = (ushort)dt.Month; 
    braziltime.wDay = (ushort)dt.Day; 
    braziltime.wHour = (ushort)(dt.Hour - 3); //today the timezone difference is 3 hours 
    braziltime.wMinute = (ushort)dt.Minute; 
    braziltime.wSecond = (ushort)dt.Second; 
    TzSpecificLocalTimeToSystemTime(ref tzi2, ref braziltime, out localtime); 
    Console.WriteLine("{0}-{1}-{2} {3}:{4}:{5}", localtime.wYear, localtime.wMonth, localtime.wDay, localtime.wHour, localtime.wMinute, localtime.wSecond); 
    break; 
    } 
    } 
    Console.ReadLine(); 
    } 
} 
} 

mais je reçois cette sortie:

local time: 11/22/2010 11:55:15 AM 
name: E. South America Standard Time st bias:-60 daylight date:3-10-0, bias:180 8:55 
2010-11-22 8:55:15 
2010-11-22 10:55:15 

Alors je prends heure locale le convertir en temps brazilian et revenir et obtenir une heure de moins. Des idées quel est le problème?

+0

ce que cela a à traiter avec C# V2 plutôt que la version de .net que vous utilisez? –

+0

Je mets le C# 2.0 là parce que C# 3.5 a TimeZoneInfo qui serait plus facile à utiliser que les APIs – JanHudecek

+0

Ian essaye apparemment de faire remarquer que le titre de votre question devrait se référer à ".NET 2.0" et non "C# 2.0", parce que les deux concepts sont distincts, et seulement légèrement liés. –

Répondre

1

Je pense que vous attendez que la première ligne de votre sortie corresponde à la dernière ligne. Cela ne se produit pas parce que la première ligne écrit l'heure locale. Vous appelez ensuite GetSystemTime et convertissez cette valeur en heure Brésil et retour. GetSystemTime renvoie UTC de sorte que la valeur que vous récupérez et que vous exportez sur la dernière ligne soit aussi UTC. En d'autres termes, vous ne comparez pas avec comme.

Si vous affichez la valeur de localtime immédiatement après l'appel de GetSystemTime, vous devez voir que la valeur est sortie après la conversion. Si vous voulez convertir de votre heure locale en heure du Brésil, vous devez probablement convertir votre heure locale en UTC, puis convertir l'heure UTC en heure du Brésil en utilisant les informations de fuseau horaire appropriées pour chaque étape.

+0

Merci, je ne me suis pas rendu compte que GetSystemTime renvoie UTC J'attendais un peu l'heure locale – JanHudecek

+0

Il y a aussi une API GetLocalTime – Steve

0

Rappelez-vous que DateTime est juste une struct afin de stocker datetime.

Vous devriez utiliser partout dans votre application UTC, et utilisez simplement Locale pour la sortie. Pour être propre, je préfère utiliser la plupart du temps utc et en faire mon converti.

0

Si c'était 3,5 ...

using System; 

// ReSharper disable once CheckNamespace 
public static class BrazilTime 
{ 
    public static DateTime Now 
    { 
     get 
     { 
      return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("E. South America Standard Time")); 
     } 
    } 
}