实现时区的转换--涉及到冬令时和夏令时的时候
Posted liwenqian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现时区的转换--涉及到冬令时和夏令时的时候相关的知识,希望对你有一定的参考价值。
时区转换
主要是用来转换时区用的,特别涉及到冬令时和夏令时的区域,这样会很烦,所以需要用个方法来转换
这个主要是创建一些模型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tools.TimeZone
{
/// <summary>
/// 国家时区类型
/// </summary>
public enum ZoneType
{
Same = 0,//普通的时区转换
Summer = 1,//启用夏时令 在夏令时的时候比冬令时早1个小时
}
/// <summary>
/// 时区
/// </summary>
public class TimeZoneModel
{
/// <summary>
/// 冬令时GMT
/// </summary>
public int GMT { get; set; }
/// <summary>
/// 这个国家应用的时区是什么
/// </summary>
public ZoneType ZoneType { get; set; }
/// <summary>
/// 时区名称
/// </summary>
public string ZoneName { get; set; }
/// <summary>
/// 时区备注
/// </summary>
public string ZoneRemark { get; set; }
/// <summary>
/// 夏时令开始时间
/// </summary>
public TimeNode BeginDate { get; set; }
/// <summary>
/// 夏时令结束时间
/// </summary>
public TimeNode EndDate { get; set; }
}
/// <summary>
/// 时间节点
/// </summary>
public class TimeNode
{
/// <summary>
/// 月份
/// </summary>
public int Month { get; set; }
/// <summary>
/// 排序方式
/// </summary>
public Sort Sort { get; set; }
/// <summary>
/// 第几个
/// </summary>
public int Num { get; set; }
/// <summary>
/// 周几
/// </summary>
public DayOfWeek DayOfWeek { get; set; }
/// <summary>
/// 几点开始
/// </summary>
public int Hours { get; set; } = 0;//一般是0点开始
}
/// <summary>
/// 查找方式
/// </summary>
public enum Sort
{
/// <summary>
/// 倒数第几个
/// </summary>
desc = 0,
/// <summary>
/// 正数第几个
/// </summary>
asc=1,
}
}
下面的是具体的方法
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tools.TimeZone
{
public static class DateZoneHelper
{
private static List<TimeZoneModel> _zoneList;
private static readonly string PATH = "TimeZone.json";
public static List<TimeZoneModel> ZoneList
{
get
{
if (_zoneList == null)
{
//从数据源中获取数据
//string Path = "TimeZone.json";
if (!File.Exists(PATH))
{
_zoneList = new List<TimeZoneModel>();
}
else
{
string str = File.ReadAllText(PATH);
//JArray array = JArray.Parse(str);
_zoneList=JsonConvert.DeserializeObject<List<TimeZoneModel>>(str);
}
}
return _zoneList;
}
}
public static TimeZoneModel GetZone(string ZoneName)
{
return ZoneList.SingleOrDefault(a => a.ZoneName == ZoneName);
}
public static DateTimeOffset ConvertDate(this DateTimeOffset dateTime, string ZoneName)
{
TimeZoneModel zone = GetZone(ZoneName);//获取当前时区的参数
return dateTime.ConvertDate(zone);
}
public static DateTimeOffset ConvertDate(this DateTimeOffset dateTime, TimeZoneModel zone)
{
if (zone==null)
{
return DateTimeOffset.MinValue;
}
DateTimeOffset date = DateTimeOffset.MinValue;
DateTime dtUTC = dateTime.UtcDateTime;
switch (zone.ZoneType)
{
case ZoneType.Summer:
DateTime dtToDate = dtUTC.AddHours(zone.GMT+1);//假设当前时间是夏令时
DateTime BeginDate = GetDateByNodeTime(dtToDate.Year,zone.BeginDate).AddHours(1);//夏令时开始时间
DateTime EndDate = GetDateByNodeTime(dtToDate.Year, zone.EndDate);//夏令时结束时间
if (BeginDate<= dtToDate&& dtToDate< EndDate)
{
date= dateTime.ToOffset(new TimeSpan(TimeSpan.TicksPerHour * (zone.GMT+1)));
}
else
{
date = dateTime.ToOffset(new TimeSpan(TimeSpan.TicksPerHour * (zone.GMT)));
//date = new DateTimeOffset(dtUTC.AddHours(zone.GMT), new TimeSpan(TimeSpan.TicksPerHour * zone.GMT));
}
break;
case ZoneType.Same:
default:
DateTime dtTemp = dtUTC.AddHours(zone.GMT);
date = dateTime.ToOffset(new TimeSpan(TimeSpan.TicksPerHour * (zone.GMT)));
//date = new DateTimeOffset(dtTemp, new TimeSpan(TimeSpan.TicksPerHour * zone.GMT));
break;
}
return date;
}
/// <summary>
/// 获取当前年份的节点
/// </summary>
/// <param name="Year">年份</param>
/// <param name="node">节点</param>
/// <returns></returns>
private static DateTime GetDateByNodeTime(int Year, TimeNode node)
{
DateTime dt = new DateTime(Year, node.Month, 1, node.Hours, 0, 0);//获取当前月的第一天
int times = 0;
switch (node.Sort)
{
case Sort.desc:
dt = dt.AddMonths(1).AddDays(-1);//获取当前月的最后一天
times = 0;
while (true)//第几个时间
{
if (dt.DayOfWeek == node.DayOfWeek)
{
times++;
if (times >= node.Num)
{
break;
}
if (times > 31)
{
Console.WriteLine($"超过天数范围:dt={dt.ToString("yyyy-MM-dd")};times={times}");
break;
}
}
dt = dt.AddDays(-1);
}
break;
case Sort.asc:
times = 0;
while (true)//第几个时间
{
if (dt.DayOfWeek == node.DayOfWeek)
{
times++;
if (times >= node.Num)
{
break;
}
if (times > 31)
{
Console.WriteLine($"超过天数范围:dt={dt.ToString("yyyy-MM-dd")};times={times}");
break;
}
}
dt = dt.AddDays(1);
}
break;
default:
break;
}
return dt;
}
public static void Add(TimeZoneModel model)
{
ZoneList.Add(model);
}
public static void Save()
{
JArray array = JArray.FromObject(ZoneList);
File.WriteAllText(PATH,array.ToString());
}
}
}
具体用法如下面的代码所示
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tools.TimeZone;
namespace 时区转换工具
{
public class Program
{
static void Main(string[] args)
{
IsZoneEnd();
Console.ReadLine();
}
/// <summary>
/// 检查是否是夏令时结束
/// </summary>
private static void IsZoneEnd()
{
for (int i = 0; i < 200; i++)
{
DateTimeOffset date = new DateTimeOffset(2019, 11, 3, 8 + i / 60, i % 60, 0, new TimeSpan(0));
DateTimeOffset offset = date.ConvertDate("US.PST");
Console.WriteLine($"i={i}当前时间是{offset.ToString("yyyy-MM-dd HH:mm:ss")}===时区是{offset.Offset}");
}
}
/// <summary>
/// 检查是否是夏令时开始
/// </summary>
private static void IsZoneBegin()
{
for (int i = 0; i < 100; i++)
{
DateTimeOffset date = new DateTimeOffset(2019, 3, 10, 9 + i / 60, i % 60, 0, new TimeSpan(0));
DateTimeOffset offset = date.ConvertDate("US.PST");
Console.WriteLine($"i={i}当前时间是{offset.ToString("yyyy-MM-dd HH:mm:ss")}===时区是{offset.Offset}");
}
}
private static void USZoneWrite()
{
TimeNode AMBegin = new TimeNode
{
Month = 3,
Num = 2,
DayOfWeek = DayOfWeek.Sunday,
Hours = 2,
Sort = Sort.asc,
};
TimeNode AMEnd = new TimeNode
{
Month = 11,
Num = 1,
DayOfWeek = DayOfWeek.Sunday,
Hours = 2,
Sort = Sort.asc,
};
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.EST",
ZoneRemark = "美国东部时间 西五区时间 美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",
GMT = -5,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.CST",
ZoneRemark = "美国中部时间(CST)(西六区时间) 美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",
GMT = -6,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.MST",
ZoneRemark = "美国山地时间(MST)(西七区时间) 美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",//东部时间 西五区时间
GMT = -7,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.PST",
ZoneRemark = "太平洋时间(西部时间)(PST)(西八区时间) 美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",//东部时间 西五区时间
GMT = -8,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.AKST",
ZoneRemark = "阿拉斯加时间(AKST)(西九区时间)美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",//东部时间 西五区时间
GMT = -9,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.ZoneList.Add(new TimeZoneModel()
{
ZoneName = "US.HST",
ZoneRemark = "夏威夷时间(HST)(西十区时间)美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时",//东部时间 西五区时间
GMT = -10,
ZoneType = ZoneType.Summer,
BeginDate = AMBegin,
EndDate = AMEnd,
});
DateZoneHelper.Save();
}
}
}
以上是关于实现时区的转换--涉及到冬令时和夏令时的时候的主要内容,如果未能解决你的问题,请参考以下文章