C#2.0特定时区
我正在.NET 2.0中开发一个遗留应用程序,我想将时间从本地时间(恰好是UTC+1)转换为巴西时间(即Windows称之为“E.南美标准时间”)并返回 我编写了以下代码来进行转换:C#2.0特定时区,c#,timezone,systemtime,C#,Timezone,Systemtime,我正在.NET 2.0中开发一个遗留应用程序,我想将时间从本地时间(恰好是UTC+1)转换为巴西时间(即Windows称之为“E.南美标准时间”)并返回 我编写了以下代码来进行转换: using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using Microsoft.Win32; namespace timezone { class P
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();
}
}
}
所以我用当地时间把它转换成巴西时间,再转换回来,就少了一个小时。
有什么问题吗?记住DateTime只是一个用来存储DateTime的结构
您应该在应用程序中的任何地方使用UTC,并且只使用区域设置作为输出。为了保持整洁,我更喜欢使用utc的大部分时间并从中进行转换。记住,DateTime只是一个用于存储DateTime的结构
您应该在应用程序中的任何地方使用UTC,并且只使用区域设置作为输出。为了保持整洁,我更喜欢大部分时间使用utc并从中进行转换。我想您希望输出的第一行与最后一行匹配。这不会发生,因为第一行写入localtime。然后调用GetSystemTime并将该值反复转换为巴西值。GetSystemTime返回UTC,因此返回的值以及最后一行的输出也应为UTC。换句话说,你不是在比较同类 如果在调用GetSystemTime后立即输出localtime的值,则应该看到该值与转换后输出的值相匹配
如果要将本地时间转换为巴西时间,则可能需要将本地时间转换为UTC,然后使用每个步骤的适当时区信息将UTC转换为巴西时间。我认为您希望输出的第一行与最后一行匹配。这不会发生,因为第一行写入localtime。然后调用GetSystemTime并将该值反复转换为巴西值。GetSystemTime返回UTC,因此返回的值以及最后一行的输出也应为UTC。换句话说,你不是在比较同类 如果在调用GetSystemTime后立即输出localtime的值,则应该看到该值与转换后输出的值相匹配 如果要将本地时间转换为巴西时间,则可能需要将本地时间转换为UTC,然后使用每个步骤的适当时区信息将UTC转换为巴西时间。如果是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"));
}
}
}
如果是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"));
}
}
}
这与C#V2而不是你正在使用的.net版本有什么关系?我把C#2.0放在那里是因为C#3.5有比APIsIan更容易使用的TimeZoneInfo。显然,APIsIan试图指出你的问题的标题应该是“.net 2.0”而不是“C#2.0”,因为这两个概念是不同的,这和C#V2有什么关系,而不是你正在使用的.net版本?我把C#2.0放在那里,因为C#3.5有比APIsIan更容易使用的TimeZoneInfo,显然是想说明问题的标题应该是“.net 2.0”而不是“C#2.0”,因为这两个概念是不同的,只是有点关联。谢谢,我没有意识到GetSystemTime返回UTC我有点期待本地时间有一个GetLocalTime API tooThanks,我没有意识到GetSystemTime返回UTC我有点期待本地时间也有一个GetLocalTime API