DateTime在毫秒中的表示?

101

我有一个SQL-server时间戳,需要将其转换为自1970年以来以毫秒为单位的时间表示。我能否使用普通的SQL实现这个功能?如果不行,我已经在C#中将其提取到了一个DateTime变量中。是否可能获得此变量的毫秒表示?

谢谢,
Teja。


1
对于后一个问题:(now - Epoch).TotalMilliseconds,其中 nowEpoch 是 DateTime 对象。 - user166390
.NET已经发展:DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - Timeless
7个回答

167

你可能正在尝试将时间转换为类Unix的时间戳,这些时间戳是以协调世界时(UTC)表示的:

yourDateTime.ToUniversalTime().Subtract(
    new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
    ).TotalMilliseconds

这还可以避免夏令时问题,因为UTC没有这些问题。


2
这个程序输出一个分数,例如:"1552678714362.79",那么".79"是从哪里来的呢? - Sharif Yazdian
3
@SharifYazdian 这正是您所期望的,它为0.79毫秒。系统时间以计时周期(ticks)为单位进行测量。鉴于1毫秒有10000个计时周期(ticks),DateTime和TimeSpan使用比整毫秒更高精度的方式来存储其值。0.79毫秒等于7900个计时周期(ticks)。如果您需要一个整数,请使用 "long ms = myTimeSpan.TotalTicks / 10000;"。 - LWChris
2
在 .NET Core (>2.1) 中,您可以使用 DateTime.UnixEpoch 来代替声明日期。 - Thom
1
这段代码存在问题:它假设 DateTime(请查看 ToUniversalTime 的合同中的注释)是本地时间,但实际上可能不是。例如,常见的是使用 DateTime.UtcNow 进行时间采样,或者它可能处于另一个时区。 - ceztko
@ceztko 对于 DateTime.UtcNow 来说,这不是一个问题,因为 UtcNow DateTime 的 Kind 属性设置为 Utc,所以 ToUniversalTime 方法不会转换任何内容。但是,如果您的 DateTime 表示的是本地或 UTC 之外的另一个时区,则可能会出现问题(在这种情况下最好使用 DateTimeOffset 而不是 DateTime)。 - Leon Lucardie

79
在 C# 中,你可以编写:
(long)(date - new DateTime(1970, 1, 1)).TotalMilliseconds

16
我建议将其转换为 long 而不是 int :) - Jon Skeet
4
如果你想倒推时间,可以使用new DateTime(1970, 1, 1).AddMilliseconds(myDateAsALong) - JackMorrissey
@JackMorrissey:AddMilliseconds()需要一个double类型的参数。隐式转换会处理这个问题,但值得注意的是。 - Axel Kemper
@JonSkeet 为什么您建议将其转换为 long 而不是 int? :) - Roxy'Pro
5
"@Roxy'Pro: int.MaxValue 表示的毫秒数约为25天。那几乎没有什么用处。" - Jon Skeet

52

从.NET 4.6开始,您可以使用DateTimeOffset对象来获取Unix毫秒数。它有一个构造函数,接受DateTime对象作为参数,因此您可以像下面演示的那样将对象传递进去。

DateTime yourDateTime;
long yourDateTimeMilliseconds = new DateTimeOffset(yourDateTime).ToUnixTimeMilliseconds();

正如其他答案中指出的那样,请确保yourDateTime指定了正确的Kind,或者使用.ToUniversalTime()将其先转换为UTC时间。

在这里您可以了解更多有关DateTimeOffset的信息。


1
在 .Net 3.5 中实际上并不存在 ToUnixTimeMilliseconds()。 - NickLokarno
2
根据MSDN的说明,ToUnixTimeMilliseconds() 函数在 .NET 4.6 及以上版本可用。 - N. M.
1
@kayleeFrye_onDeck 这个帖子的问题是关于从数据库中提取时间戳,所以你关于.Now的评论并不直接适用于这个问题。 - Bob

3

DateTimeExtensions类中有ToUnixTime()ToUnixTimeMs()方法。

DateTime.UtcNow.ToUnixTimeMs()


2

这是将日期时间转换为C# Unix时间戳(毫秒)的另一种解决方案。

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static long GetCurrentUnixTimestampMillis()
{
    DateTime localDateTime, univDateTime;
    localDateTime = DateTime.Now;          
    univDateTime = localDateTime.ToUniversalTime();
    return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
} 

2
SELECT CAST(DATEDIFF(S, '1970-01-01', SYSDATETIME()) AS BIGINT) * 1000

这并不能给你完全的精确度,但是DATEDIFF(MS...会导致溢出。如果秒级别的精度足够,那么使用下面的方法可以解决问题。


1

使用Andoma的答案,这是我正在做的:

您可以创建一个类似于以下结构体或类:

struct Date
    {
        public static double GetTime(DateTime dateTime)
        {
            return dateTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
        }

        public static DateTime DateTimeParse(double milliseconds)
        {
            return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(milliseconds).ToLocalTime();
        }

    }

你可以按照以下方式在你的代码中使用它

DateTime dateTime = DateTime.Now;

double total = Date.GetTime(dateTime);

dateTime = Date.DateTimeParse(total);

我希望这可以帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接