我只是想不通...。请参阅第二个代码段中的调用方法。您将看到一条注释为 // _ time = time.ToUTCString(); 的行,转到第一个代码段以查看方法 ToUTCString()。您会看到它需要日期时间,将其转换为世界时,然后减去UnixEpoch即可得出TotalSeconds。然后,它将值转换为Int64(),最后转换为字符串。我尝试调用方法ToLocalString,但这也在更改日期。
我传递的日期是我想要转换为Int64并最终转换为字符串的日期。我传递的日期时间。未更改。
我不想更改传入的日期。我总是传入从12:00:00 AM(或00:00:00)开始的日期,而这正是我一直想要的时间。 这两种方法都会更改日期和/或时间。我传递的日期为 2017年6月1日上午12:00:00 ,但有时它更改为 2017年5月31日04:00:00 或保留日期,但时间不正确。 Dark Sky要求日期为Convert.ToInt64(milliseconds)的值,然后转换为字符串。
有人知道如何以毫秒为单位将传入的确切日期和时间转换为Int64吗?
我有以下扩展类:
public static class Extensions
{
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static string ToLocalString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToLocalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
public static string ToUTCString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToUniversalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
}
这是调用方法:
public ForecastIORequest(string apiKey, float latF, float longF, DateTime time, Unit unit, Language? lang = null, Extend[] extend = null, Exclude[] exclude = null)
{
_apiKey = apiKey;
_latitude = latF.ToString(CultureInfo.InvariantCulture);
_longitude = longF.ToString(CultureInfo.InvariantCulture);
//_time = time.ToUTCString();
_time = time.ToLocalString();
//DateTime t = _time.
_unit = Enum.GetName(typeof(Unit), unit);
_extend = (extend != null) ? RequestHelpers.FormatExtendString(extend) : "";
_exclude = (exclude != null) ? RequestHelpers.FormatExcludeString(exclude) : "";
_lang = (lang != null) ? RequestHelpers.FormatLanguageEnum(lang) : Language.en.ToString();
}
答案 0 :(得分:2)
您在这里处理日期的方式存在一个基本问题,如果我将其归结为一件事,我认为问题在于ToUniversalTime()
不能像您认为的那样工作。< / p>
ToUniversalTime()
的作用是,简单地给UTC
一个在不同时区中定义的时间。例如,假设我的当地时间是UTC-7
。因此,如果我定义一个DateTime
对象而未指定DateTimeKind
并将其值设置为2017/6/1 9:00:00
,则意味着当时实际的{{1 }}时间是UTC
,此时2017/6/1 16:00:00
将为您提供一个具有该值的ToUniversalTime()
对象。
让我稍微更改您的DateTime
方法,然后向您展示它的问题。它现在返回的是ToUTCString()
而不是long
的值,我将第一行代码分解为两行。
string
请注意,在您的public static long ToUTC(this DateTime _input)
{
var utcTime = _input.ToUniversalTime();
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
类中,Extensions
对象的UnixEpoch
被设置为DateTimeKind
。为了便于理解,我将日期更改为UTC
。
2017/6/1 8:00:00
现在让我们使用private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
对象设置为DateTime
的{{1}}对象调用该方法。
DateTimeKind
现在,这里所有内容都在UTC
中,您应该看到预期的输出,如下所示:
3600
6/1/2017 09:00:00
到目前为止一切都很好。
现在要稍作更改,就像在示例中一样,将// dateObj will have time 2017/6/1 9:00:00 _in UTC_.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
// This method converts to UTC, but it's already in UTC, so no actual conversion takes place.
// Then subtracts UnixEpoch from it, which is also in UTC.
long dateInLong = dateObj.ToUTC();
// The difference is one hour, so dateInLong will be 3600.
Console.WriteLine(dateInLong);
// This method adds the above difference to UnixEpoch, and displays the time.
Console.WriteLine(dateInLong.ToDateTime());
设置为local而不是UTC
。
dateObj
现在,以上UTC
将有时间// Notice that the object is in local time now.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
,但是我的本地时间。我的实际位置是dateObj
,所以请注意,这意味着9:00:00
对我来说是当地时间UTC-7
UTC。但是请注意,我们尚未更改9AM
对象,该对象仍位于4PM
中,并且时间设置为UnixEpoch
。因此,UTC
将是8AM UTC
(8小时x 60分钟x 60秒)。因此,在调用您的dateInLong
方法时,它会将28,800
的时间增加ToDateTime()
秒,并作为28,000
对象返回,该对象现在的时间为8AM UTC
。
28800
6/1/2017 16:00:00
这就是为什么取决于您设置DateTime
的时间,输出更改的时间,如您所说的那样。
您需要确定要使用的时区,并遵守该时区。一种选择是摆脱所有4PM UTC
的转化,并在当地时间设置所有时间。
dateObj
另一个选项,将EVERYTHING设置为UTC,但随后必须确保调用UTC
的{{1}}对象是在UTC中定义的,而不是本地的。
所以:
public static class Extensions
{
// NOT set to UTC
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static long ToUTC(this DateTime _input)
{
// NOT converted to UTC. So... change variable names accordingly.
var utcTime = _input;
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
}
class Program
{
static void Main(string[] args)
{
// Notice that the object is in local time and NOT UTC.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
Console.ReadLine();
}
}
和
DateTime
最后
ToUTC()
在第二个代码段中,您遇到了一个更大的问题。在private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
构造函数中,您将时间节省为var utcTime = _input.ToUniversalTime();
。我认为这不是理想的解决方案。因为当您发现困难的方式时,根据创建调用对象的时区,您的时差会有所不同。而且您无法知道哪个。
我宁愿按原样存储var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
对象,并在考虑到时区的情况下读取它并在需要时计算差值。
希望这会有所帮助。
答案 1 :(得分:1)
请参见DateTime.Ticks-一毫秒内有10,000个滴答声。只需花费DateTime.Ticks / 10000
(一万),就可以计算出毫秒数。
这是一种简单的扩展方法,可将毫秒数设为长整数(即Int64):
public static long ToMilliseconds(this DateTime dateTime)
{
return dateTime.Ticks / 10000;
}