Cách lấy dấu thời gian unix trong C #


399

Tôi đã xem xét xung quanh stackoverflow, và thậm chí đã xem xét một số câu hỏi được đề xuất và dường như không có câu trả lời nào, làm thế nào để bạn có được dấu thời gian unix trong C #?


Câu trả lời:


597

Bạn nhận được dấu thời gian unix trong C # bằng cách sử dụng DateTime.UtcNowvà trừ thời gian kỷ nguyên 1970-01-01.

ví dụ

Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

DateTime.UtcNowcó thể được thay thế bằng bất kỳ DateTimeđối tượng nào bạn muốn lấy dấu thời gian unix cho.

Ngoài ra còn có một lĩnh vực, DateTime.UnixEpochđược MSFT ghi lại rất kém , nhưng có thể thay thế chonew DateTime(1970, 1, 1)


28
Nhận xét thay mặt cho @wdhough. "Câu trả lời này có giới hạn với giới hạn của Int32, theo tôi là 2.147.483.647. Theo onlineconversion.com/unix_time.htmlm điều này tương đương với thời gian của Tue, ngày 19 tháng 1 năm 2038 03:14:07 GMT Tôi đoán bất kỳ loại số thay thế nào , gấp đôi, dài, v.v ... cuối cùng cũng sẽ có một giới hạn, nhưng tôi nghĩ nó đáng được đề cập. Tôi chọn ở đây lâu vì tôi muốn có một con số. Hy vọng điều này sẽ giúp "
IsmailS

11
Dấu thời gian unix theo truyền thống là số nguyên 32 bit và có phạm vi '1970-01-01 00:00:01' UTC đến '2038-01-19 03:14:07' UTC.
the_nuts

89
Thật điên rồ khi chuyển đổi thời gian UNIX không có trong thư viện chuẩn như là một phần của DateTime.
xingyu

7
Hoặc sử dụng số học số nguyên:DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Anton Petrov

2
Thời gian bị trừ không cần phải là UTC?
jjxtra

572

Kể từ .NET 4.6, có DateTimeOffset.ToUnixTimeSeconds().


Đây là một phương thức cá thể, vì vậy bạn sẽ gọi nó theo một thể hiện của DateTimeOffset. Bạn cũng có thể truyền bất kỳ trường hợp nào DateTime, mặc dù hãy coi chừng múi giờ .

Để có được dấu thời gian hiện tại:

DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Để lấy dấu thời gian từ một DateTime:

DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();

126
Tốt Đó là khoảng thời gian
bizzehdee 16/2/2016

35
@MattBorja Rất may, nó trả lại một Int64- vào thời điểm đó, chúng ta sẽ không sử dụng Trái đất nhiều năm nữa vì thiếu Trái đất.
Bob

24
Đối với bất kỳ ai khác thắc mắc, bạn có thể nhận được dấu thời gian hiện tại vớiDateTimeOffset.Now.ToUnixTimeSeconds()
kR105

8
@bizzehdee, Pun dự định?
st0le

5
Bạn có thể nhận được UTC unixtimestamp với: DateTime Offerset.UtcNow.ToUnixTimeSeconds ()
Yair Levi

39

Bạn cũng có thể sử dụng Ticks. Tôi đang mã hóa cho Windows Mobile vì vậy không có bộ phương pháp đầy đủ. TotalSeconds không có sẵn cho tôi.

long epochTicks = new DateTime(1970, 1, 1).Ticks;
long unixTime = ((DateTime.UtcNow.Ticks - epochTicks) / TimeSpan.TicksPerSecond);

hoặc là

TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;

1
Lỗi cho giải pháp thứ hai: Không thể chuyển đổi loại nguồn 'gấp đôi' thành loại mục tiêu 'dài'.
Pixar

@Pixar: Mẫu thứ hai đã được sửa
JBert

5
new DateTime(1970, 1, 1)tạo ra một thời gian với Kindtài sản không xác định . Những gì bạn thực sự muốn new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)là thực sự chính xác
mất

Từ .NET Core 2.1 Bạn có thể sử dụng DateTime.UnixEpoch thay vì DateTime mới (1970, 1, 1) xem docs.microsoft.com/en-us/dotnet/api/iêu
Jaa H

27

Đây là những gì tôi sử dụng:

public long UnixTimeNow()
{
    var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
    return (long)timeSpan.TotalSeconds;
}

Hãy nhớ rằng phương pháp này sẽ trả về thời gian là Thời gian chuyển tiếp phối hợp (UTC).


(TotalSeconds có doubleloại; kéo dài nó sẽ gây mất độ chính xác.)
thắn

Bạn đúng, nhưng chúng tôi không phải lo lắng về điều đó trong vài nghìn năm :)
Bartłomiej Mucha

21

Cắt ngắn .TotalSeconds là quan trọng vì nó được định nghĩa làthe value of the current System.TimeSpan structure expressed in whole fractional seconds.

Và làm thế nào về một phần mở rộng cho DateTime? Cái thứ hai có lẽ khó hiểu hơn là nó có giá trị cho đến khi phần mở rộng thuộc tính tồn tại.

/// <summary>
/// Converts a given DateTime into a Unix timestamp
/// </summary>
/// <param name="value">Any DateTime</param>
/// <returns>The given DateTime in Unix timestamp format</returns>
public static int ToUnixTimestamp(this DateTime value)
{
    return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}

/// <summary>
/// Gets a Unix timestamp representing the current moment
/// </summary>
/// <param name="ignored">Parameter ignored</param>
/// <returns>Now expressed as a Unix timestamp</returns>
public static int UnixTimestamp(this DateTime ignored)
{
    return (int)Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}

2
Phương pháp mở rộng rõ ràng là cách để làm điều này gọn gàng. Đây là một câu trả lời xuất sắc, trưởng thành - và tôi không hiểu tại sao nó có quá ít phiếu bầu. Khá chắc chắn rằng Robba là chính xác - truyền đầu ra dưới dạng (int) tự động cắt kết quả. (Nghĩa đen bỏ qua phần thập phân của kép).
Stephanie

4
(DateTime bị bỏ qua này) rất, rất sai lệch
Lars Corneliussen

6

Khi bạn trừ 1970 từ thời điểm hiện tại, hãy lưu ý rằng thời gian thường sẽ có trường không bằng mili giây. Nếu vì lý do nào đó bạn quan tâm đến mili giây, hãy ghi nhớ điều này.

Đây là những gì tôi đã làm để giải quyết vấn đề này.

 DateTime now = UtcNow();

 // milliseconds Not included.
 DateTime nowToTheSecond = new DateTime(now.Year,now.Month,now.Day,now.Hour,now.Minute,now.Second); 

 TimeSpan span = (date - new DateTime(1970, 1, 1, 0, 0, 0, 0));

 Assert.That(span.Milliseconds, Is.EqualTo(0)); // passes.

5

Đây là những gì tôi sử dụng.

 public class TimeStamp
    {
        public Int32 UnixTimeStampUTC()
        {
            Int32 unixTimeStamp;
            DateTime currentTime = DateTime.Now;
            DateTime zuluTime = currentTime.ToUniversalTime();
            DateTime unixEpoch = new DateTime(1970, 1, 1);
            unixTimeStamp = (Int32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
            return unixTimeStamp;
        }
}

có lẽ làm cho nó trở thành một phương thức mở rộng của DateTime
bizzehdee

3

Tôi đã kết hợp các cách tiếp cận thanh lịch nhất với phương pháp tiện ích này:

public static class Ux {
    public static decimal ToUnixTimestampSecs(this DateTime date) => ToUnixTimestampTicks(date) / (decimal) TimeSpan.TicksPerSecond;
    public static long ToUnixTimestampTicks(this DateTime date) => date.ToUniversalTime().Ticks - UnixEpochTicks;
    private static readonly long UnixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
}

2

Giải pháp này đã giúp trong tình huống của tôi:

   public class DateHelper {
     public static double DateTimeToUnixTimestamp(DateTime dateTime)
              {
                    return (TimeZoneInfo.ConvertTimeToUtc(dateTime) -
                             new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
              }
    }

sử dụng trình trợ giúp trong mã:

double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)

0

Có một ToUnixTimeMilliseconds cho DateTimePackset trong Hệ thống

Bạn có thể viết phương thức tương tự cho DateTime:

public static long ToUnixTimeSeconds(this DateTime value)
{
    return value.Ticks / 10000000L - 62135596800L;
}

10000000L - chuyển đổi tick thành giây

62135596800L - chuyển đổi 01.01.01 thành 01.01.1978

Không có vấn đề với Utc và rò rỉ



0

Dưới đây là lớp mở rộng 2 chiều hỗ trợ:

  • Nội địa hóa múi giờ
  • Nhập \ đầu ra tính bằng giây hoặc mili giây.

Trong trường hợp của OP, cách sử dụng là:

DateTime.Now.ToUnixtime();

hoặc là

DateTime.UtcNow.ToUnixtime();

Mặc dù một câu trả lời trực tiếp tồn tại, tôi tin rằng sử dụng một cách tiếp cận chung là tốt hơn. Đặc biệt bởi vì rất có thể đó là một dự án cần chuyển đổi như thế này, dù sao cũng sẽ cần các tiện ích mở rộng này, vì vậy tốt hơn hết là sử dụng cùng một công cụ cho tất cả.

    public static class UnixtimeExtensions
    {
        public static readonly DateTime UNIXTIME_ZERO_POINT = new DateTime(1970, 1, 1, 0, 0,0, DateTimeKind.Utc);

        /// <summary>
        /// Converts a Unix timestamp (UTC timezone by definition) into a DateTime object
        /// </summary>
        /// <param name="value">An input of Unix timestamp in seconds or milliseconds format</param>
        /// <param name="localize">should output be localized or remain in UTC timezone?</param>
        /// <param name="isInMilliseconds">Is input in milliseconds or seconds?</param>
        /// <returns></returns>
        public static DateTime FromUnixtime(this long value, bool localize = false, bool isInMilliseconds = true)
        {
            DateTime result;

            if (isInMilliseconds)
            {
                result = UNIXTIME_ZERO_POINT.AddMilliseconds(value);
            }
            else
            {
                result = UNIXTIME_ZERO_POINT.AddSeconds(value);
            }

            if (localize)
                return result.ToLocalTime();
            else
                return result;
        }

        /// <summary>
        /// Converts a DateTime object into a Unix time stamp
        /// </summary>
        /// <param name="value">any DateTime object as input</param>
        /// <param name="isInMilliseconds">Should output be in milliseconds or seconds?</param>
        /// <returns></returns>
        public static long ToUnixtime(this DateTime value, bool isInMilliseconds = true)
        {
            if (isInMilliseconds)
            {
                return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalMilliseconds;
            }
            else
            {
                return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalSeconds;
            }
        }
    }

Cẩn thận không nhầm lẫn giữa các định dạng mili giây và giây (trường hợp tốt nhất là ngoại lệ, tệ nhất là chuyển đổi phi logic) Tôi đã mặc định đầu vào \ đầu ra thành định dạng mili giây. Nếu bạn thích sử dụng định dạng giây làm mặc định, chỉ cần chuyển isInMilliseconds = true (trong cả hai phương thức) thành false.
SingleFlake

0

Tôi đã sử dụng điều này sau khi vật lộn một lúc, nó cũng phục vụ cho phần bù múi giờ:

    public double Convert_DatTime_To_UNIXDATETIME(DateTime dt)
    {
        System.DateTime from_date = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
        double unix_time_since = dt.Subtract(from_date).TotalMilliseconds;

        TimeSpan ts_offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);

        double offset = ts_offset.TotalMilliseconds;

        return unix_time_since - offset;
    }

-1

Mã đơn giản mà tôi đang sử dụng:

public static long CurrentTimestamp()
{
   return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000);
}

Mã này đang đưa ra dấu thời gian unix, tổng số mili giây từ 1970-01-01 đến nay.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.