2010-11-22 9 views
1

私は.NET 2.0のレガシーアプリケーションで作業していますが、現地時間(現時点ではUTC + 1)からブラジルの時間(つまり、「E.南アメリカ標準Windowsが呼び出すように「時間」)、そして戻ってきます。C#2.0の特定のタイムゾーン

私は一緒に私は、変換を行うために思い付いたこのコードを置く:

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(); 
    } 
} 
} 

を、私はこの出力を得る:ブラジルの時間に変換

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 

だから私は現地時間がかかるし、戻って、1時間少なくする。 何か問題がありますか?

+0

た場合は? –

+0

C#3.5には、APIよりも使いやすいTimeZoneInfoがありますので – JanHudecek

+0

Ianは明らかにあなたの質問のタイトルが「C#2.0」ではなく「.NET 2.0」を指すようにしています。 2つの概念は異なるものであり、わずかに関連しているに過ぎないからです。 –

答えて

1

出力の最初の行が最後の行に一致すると予想していると思います。最初の行がlocaltimeを書き込むので、これは起こっていません。その後、GetSystemTimeを呼び出し、その値をブラジルの時刻に変換して元に戻します。 GetSystemTimeはUTCを返すので、最後の行に戻って出力する値もUTCでなければなりません。言い換えれば、あなたは好きなものと似ているわけではありません。

GetSystemTimeを呼び出した直後にlocaltimeの値を出力すると、変換後の出力値と一致するはずです。

現地時間からブラジル時間に変換する場合は、おそらく現地時間をUTCに変換し、各ステップの適切なタイムゾーン情報を使用してUTCからブラジル時間に変換する必要があります。

+0

ありがとう、私はGetSystemTimeがUTCを返すことに気付きませんでした。私はちょっとローカルタイムを期待していました。 – JanHudecek

+0

GetLocalTime APIもあります – Steve

0

DateTimeはdatetimeを格納するための単なる構造体であることを覚えておいてください。

あなたのアプリケーションのどこにでもUTCを使用し、出力にはロケールを使用するだけです。きれいにするために、私はutcのほとんどの時間を使い、それから変換するのが好きです。

0

これは、むしろその後、C#V2で使用している.NETのバージョンを対処するために持っているものを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")); 
     } 
    } 
} 
関連する問題