C #에서 에포크 시간을 어떻게 변환합니까?


377

C #에서 Unix epoch 시간 을 실시간으로 어떻게 변환 합니까? (1970 년 1 월 1 일 시작)


1
내가 빠진 것이 아니라면 "에포크 (epoch)"는 단순히 특정 시간 관리 체계의 원점입니다. 예는 1/1/0001, 1/1/1970 및 1/1/2000입니다. 그것은 체계 (예 : 율리우스) 자체보다는 체계의 특성에 가깝습니다.
Bob Kaufman

8
에포크 이후의 시간은 1970 년 1 월 1 일 이후의 초 수입니다.
Taylor Leese

13
@Taylor 그것은 유닉스 시대의 신기원 일 것입니다. 아마도 옳 겠지만, 유일하게 유효한 신기원은 아닙니다. 유닉스 시간 사용자는 그 시점에서 자신을 혼동해서는 안됩니다.
Joel Coehoorn

답변:


563

1970 년 1 월 1 일 자정 (UTC) 이후의 초 수로 정의되는 Unix 시간 을 의미한다고 가정합니다 .

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

74
이것이 올바르게 작동하려면 .AddSeconds를 .AddMilliseconds로 변경해야했습니다. 올바른 결과를 얻으려면 숫자가 초인지 밀리 초인지를 알아야합니다. 예를 들어 다음 날짜는 1406310305188 (2014 년 7 월 25 일)입니다. epochconverter.com에서 전환 결과를 확인할 수도 있습니다.
jrandomuser

5
AddSeconds가 double을 허용하므로 double로 다운 캐스트되기 때문에 매개 변수 유형을 double로 변경하거나 인수의 64 비트 정밀도 중 53 비트 만 유지되도록 메소드 설명에 고지 사항을 추가해야합니다.
tomosius

6
@jrandomuser : 유닉스 시대는 전통적으로 The Epoch 이후 초로 표시됩니다 . 이후 The Epoch (예 : JavaScript) 이후 밀리 초 를 사용하는 것이 일반적 이었지만 기본 정의는 초입니다. 결론은 입력 값이 무엇인지 (초, 밀리 초, 틱 등) 알고 올바른 AddXYZ방법을 사용하십시오 .
TJ Crowder

먼저 AddMilliseconds로 시도하고 연도가 1970 년이면 AddSeconds를 수행하십시오. 이렇게하면 밀리 초 또는 초를 걱정할 필요없이 항상 작동합니다. 또한 오버플로 예외를 방지 할 수 있습니다. AddSeconds에 많은 수를 전달하면 코드 충돌이 발생합니다
Tono Nam

213

닷넷 (V4.6)의 최신 버전은 단지 내장 추가 된 유닉스 시간 변환을 지원합니다. 여기에는 초 또는 밀리 초로 표시되는 유닉스 시간과 출발 시간이 모두 포함됩니다.

  • 초 단위의 유닉스 시간 DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset 초 단위의 유닉스 시간 :

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • 밀리 초 단위의 유닉스 시간 DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset 밀리 초 단위의 유닉스 시간 :

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();

참고 :이 메소드는로 (과) 변환합니다 DateTimeOffset. DateTime표현 을 얻으려면 단순히 DateTimeOffset.DateTime속성을 사용하십시오 .

DateTime dateTime = dateTimeOffset.UtcDateTime;

1
나는 얻고 'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'난이 해결에 대한 갈 것이라고 어떻게?
Happy Bird

@HappyBird .NET 4.6 이상입니까?
i3arnon

같은 일 - 4.7.2 및 DateTimeOffset으로 대한 FromUnixTimeMilliseconds 방법이 없습니다 ...
Mikhail_Sam

알았어 새 객체를 만들 필요가 없습니다. 정적 방법입니다.
Mikhail_Sam

처음에는 기본값이 약간 혼란 스럽습니다. Bc 1000은 밀리 초를 초 단위로 변환하는 요소입니다.
BluE

169

LukeH에 대한 모든 확신을 가지고 쉽게 사용할 수 있도록 몇 가지 확장 방법을 모았습니다.

public static DateTime FromUnixTime(this long unixTime)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return epoch.AddSeconds(unixTime);
}

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date - epoch).TotalSeconds);
}

위의 것을 CodesInChaos에서 아래의 설명을 참고 FromUnixTime리턴한다 DateTimeA를 KindUtc괜찮지 만, 위의 어떤은 ToUnixTime훨씬 더 의심 점에서 고려하지 않는 종류의 것입니다 DateTime주어진 date것입니다. 을 허용하기 위해 dateKind존재 중 하나 Utc또는 Local사용 ToUniversalTime:

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

ToUniversalTimeLocal(또는 Unspecified) DateTime을 로 변환합니다 Utc.

DateTime에서 epoch로 이동할 때 epoch DateTime 인스턴스를 작성하지 않으려면 다음을 수행하십시오.

public static long ToUnixTime(this DateTime date)
{
    return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}

6
ToUnixTime날짜가 Utc 인 경우에만 올바르게 작동합니다. 수표를 추가하거나 변환하십시오. (개인적으로 나는 수표를 선호합니다)
CodesInChaos

2
지난 몇 시간 동안 이것이 왜 효과가 없는지 알아 냈습니다. 당신의 작업에 필요 milliseconds 없는 초!
KristianB

7
@KristianB : "유닉스 시간"은 The Epoch 이후 전통적으로 밀리 초가 아닌 초입니다. 요즘에는 누군가가 어떤 정의를 사용하고 있는지주의해서 확인하고 있습니다. 초는 충분히 좋았으며 서명 된 32 비트 값으로 The Epoch의 양쪽에 합리적인 범위를 제공했습니다. (그리고 2038 년 1 월 19 일 오전 3시 14 분 직후에 GMT는 일부에게는 좋지 않은 시간이 될 수 있습니다 ...) 밀리 초를 사용하는 것은 우리가 일상적으로 64 비트 값을 던질 수 있기 때문에보다 현대적인 관행입니다 (둘 다 정수) 배정 밀도 IEEE-754) ...
TJ Crowder

5
코드 주셔서 감사합니다. Epoch 기본을 만들 때 약간의 권장 사항 만 있습니다. Millisecond 값을 0으로 명시 적으로 설정해야합니다. 즉 var epoch = new DateTime (1970, 1, 1, 0 / * h * /, 0 / * m * /, 0 / * s * /, 0 / * ms * /, DateTimeKind.Utc); 명시 적으로 설정하지 않으면 밀리 초 값이 1로 나타납니다. 이로 인해 테스트에서 일부 불일치가 발생했습니다.
ctrlplusb

1
당신은 사용해야 AddMilliseconds당신은 플로트 NOT 더블을 사용해야합니다. 그렇지 않으면 시간이 잘못됩니다.
Axel

25

실제로는 초가 아닌 밀리 초 (밀리 초)를 추가하려고합니다. 초를 추가하면 범위를 벗어난 예외가 발생합니다.


왜 그런 겁니까? epochconverter.com 1/1/970 이 아닌 ms 이후의 시간 (초)을 추가한다고 말합니다.
Jamie R Rytlewski 2016 년

당신이 ms에서 가고 있다면 당신은 분명히 원 AddMillis하고 당신이 몇 초에서 시작한다면 당신은 분명히 원합니다 AddSeconds.
구두

초를 사용할 때 계속 범위를 벗어나는 것과 같은 문제가있었습니다. 내가 변환하려고했던 유닉스 시간은 밀리 초였습니다. 나는 그것이 초 안에 있다고 생각했다. 일부 유닉스 시간은 밀리 초 단위로 측정됩니다.
DoodleKana

Unix Time은 일반적으로 초 단위로 표시되지만 0.001은 유효한 초 수 (= 1ms)입니다. 확실하지 않은 경우 가능한 최대 정밀도를 사용하십시오.
Scott

9

더 나은 성능을 원하면이 버전을 사용할 수 있습니다.

public const long UnixEpochTicks = 621355968000000000;
public const long TicksPerMillisecond = 10000;
public const long TicksPerSecond = TicksPerMillisecond * 1000;

//[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DateTime FromUnixTimestamp(this long unixTime)
{
    return new DateTime(UnixEpochTicks + unixTime * TicksPerSecond);
}

net471 아래의 빠른 벤치 마크 (BenchmarkDotNet) 에서이 번호를 얻습니다.

        Method |     Mean |     Error |    StdDev | Scaled |
-------------- |---------:|----------:|----------:|-------:|
         LukeH | 5.897 ns | 0.0897 ns | 0.0795 ns |   1.00 |
      MyCustom | 3.176 ns | 0.0573 ns | 0.0536 ns |   0.54 |

LukeH 버전 보다 2 배 빠름 (성능이 문제가되는 경우)

이것은 DateTime이 내부적으로 작동하는 방식과 유사합니다.


9

DateTimeOffset.ToUnixTimeMilliseconds () 메소드를 사용하십시오. 1970-01-01T00 : 00 : 00.000Z 이후 경과 된 밀리 초 수를 리턴합니다.

이것은 Framework 4.6 이상에서만 지원됩니다

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

DateTimeOffset.ToUnixTimeMilliseconds에 잘 설명되어 있습니다.

다른 방법은 다음을 사용하는 것입니다.

long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;

초만으로 EPOCH를 얻으려면 다음을 사용할 수 있습니다

 var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

다음 방법으로 Epoch를 로 변환하십시오.DateTime

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}

DateTime.Ticks- 각 틱은 "100 나노초"이므로 기억해야 할 추가 '것'입니다. 둘 다 생략 .Ticks하면 DateTime 빼기에서 멋진 TimeSpan 인스턴스를 다시 얻을 수 있습니다.
user2864740

8
// convert datetime to unix epoch seconds
public static long ToUnixTime(DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

DateTime 개체에 ToUniversalTime ()을 사용해야합니다.


5

에포크 변환에 다음 확장 방법을 사용합니다.

public static int GetEpochSeconds(this DateTime date)
    {
        TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
        return (int)t.TotalSeconds;
    }

public static DateTime FromEpochSeconds(this DateTime date, long EpochSeconds)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(EpochSeconds);

    }

2

밀리 초 또는 초 사용에 대해 걱정하지 않으려면 다음을 수행하십시오.

    public static DateTime _ToDateTime(this long unixEpochTime)
    {
        DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var date = epoch.AddMilliseconds(unixEpochTime);

        if (date.Year > 1972)
            return date;

        return epoch.AddSeconds(unixEpochTime);
    }

에포크 시간이 초 단위이면 1972 년에 밀리 초를 추가 할 수있는 방법이 없습니다.


1

4.6을 사용하지 않는 경우 소스 : System.IdentityModel.Tokens 가 도움이 될 수 있습니다 .

    /// <summary>
    /// DateTime as UTV for UnixEpoch
    /// </summary>
    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// Per JWT spec:
    /// Gets the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the desired date/time.
    /// </summary>
    /// <param name="datetime">The DateTime to convert to seconds.</param>
    /// <remarks>if dateTimeUtc less than UnixEpoch, return 0</remarks>
    /// <returns>the number of seconds since Unix Epoch.</returns>
    public static long GetIntDate(DateTime datetime)
    {
        DateTime dateTimeUtc = datetime;
        if (datetime.Kind != DateTimeKind.Utc)
        {
            dateTimeUtc = datetime.ToUniversalTime();
        }

        if (dateTimeUtc.ToUniversalTime() <= UnixEpoch)
        {
            return 0;
        }

        return (long)(dateTimeUtc - UnixEpoch).TotalSeconds;
    }    

예를 들어 JWT의 감사합니다. 그건 그렇고, 그것을 사용하려면 다음을 사용하십시오 : using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
liquide

0

경우 당신은 변환해야 timeval 형 구조체 포함 (초, 마이크로 초) UNIX time로를 DateTime정밀도를 잃지 않고,이 방법은 다음과 같습니다

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private DateTime UnixTimeToDateTime(Timeval unixTime)
{
    return _epochTime.AddTicks(
        unixTime.Seconds * TimeSpan.TicksPerSecond +
        unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000);
}


-4

내 해결책은 다음과 같습니다.

public long GetTime()
{
    DateTime dtCurTime = DateTime.Now.ToUniversalTime();

    DateTime dtEpochStartTime = Convert.ToDateTime("1/1/1970 0:00:00 AM");

    TimeSpan ts = dtCurTime.Subtract(dtEpochStartTime);

    double epochtime;

    epochtime = ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds);   

    return Convert.ToInt64(epochtime);
}

7
이것은 윤년과 윤초 등을 설명합니까?
Jodrell

1
이전 코멘트에 확장하려면, 여기에 시간이 복잡 이유를 설명하는 짧은 동영상입니다 왜 당신은 스스로 일을 시도해서는 안 : youtube.com/watch?v=-5wpm-gesOY
vmrob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.