Come si converte il tempo di Unix in tempo reale in C #? (Epoca inizio 1/1/1970)
Come si converte il tempo di Unix in tempo reale in C #? (Epoca inizio 1/1/1970)
Risposte:
Presumo che intendi l' ora di Unix , che è definita come il numero di secondi dalla mezzanotte (UTC) del 1 ° gennaio 1970.
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);
AddXYZ
metodo giusto .
L' ultima versione di .Net (v4.6) ha appena aggiunto il supporto integrato per le conversioni temporali Unix. Ciò include sia il tempo di andata e ritorno di Unix rappresentato da secondi o millisecondi.
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
tempo Unix in secondi:long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
al tempo Unix in millisecondi:long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
Nota: questi metodi vengono convertiti da e verso DateTimeOffset
. Per ottenere una DateTime
rappresentazione è sufficiente utilizzare la DateTimeOffset.DateTime
proprietà:
DateTime dateTime = dateTimeOffset.UtcDateTime;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
Come potrei fare per risolvere questo?
Con tutto il merito di LukeH, ho messo insieme alcuni metodi di estensione per un facile utilizzo:
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);
}
Nota il commento qui sotto di CodesInChaos che quanto sopra FromUnixTime
restituisce a DateTime
con a Kind
di Utc
, il che va bene, ma quanto sopra ToUnixTime
è molto più sospetto in quanto non tiene conto del tipo di DateTime
dato date
. Per consentire date
's Kind
essere uno Utc
o Local
, uso 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);
}
ToUniversalTime
convertirà un Local
(o Unspecified
) DateTime
in Utc
.
se non si desidera creare l'istanza DateTime di epoca quando ci si sposta da DateTime a epoca è possibile anche:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
funziona correttamente solo se la data è in Utc. Aggiungi un segno di spunta o convertilo. (Personalmente preferisco il controllo)
milliseconds
non secondi !!!
AddMilliseconds
e dovresti usare Double NOT Float. Altrimenti finirai con un momento sbagliato.
In realtà si desidera aggiungere Millisecondi (millisecondi), non secondi. L'aggiunta di secondi ti darà un'eccezione fuori portata.
AddMillis
e se stai partendo da pochi secondi, ovviamente, vuoi AddSeconds
.
Se vuoi prestazioni migliori puoi usare questa versione.
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);
}
Da un rapido benchmark (BenchmarkDotNet) sotto net471 ottengo questo numero:
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 |
2x più veloce rispetto alla versione di LukeH (se la performance mater)
Questo è simile al funzionamento interno di DateTime.
Usa il metodo DateTimeOffset.ToUnixTimeMilliseconds () Restituisce il numero di millisecondi trascorsi dal 1970-01-01T00: 00: 00.000Z.
Questo è supportato solo con Framework 4.6 o versioni successive
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
È ben documentato qui DateTimeOffset.ToUnixTimeMilliseconds
L'altra via d'uscita è usare quanto segue
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
Per ottenere l'EPOCH in pochi secondi puoi usare
var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
e converti Epoch
in DateTime
con il seguente metodo
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
.Ticks
, si otterrebbe una bella istanza TimeSpan dalla sottostrazione DateTime.
// 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);
}
Dovrebbe usare ToUniversalTime () per l'oggetto DateTime.
Uso i seguenti metodi di estensione per la conversione di epoca
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);
}
Per non preoccuparti di usare millisecondi o secondi, fai semplicemente:
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);
}
Se il tempo è in secondi, non è possibile passare l'anno 1972 aggiungendo millisecondi.
Se non si utilizza 4.6, questo può aiutare Source: 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;
}
using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
In caso di necessità di convertire una struct timeval (secondi, microsecondi) contenente UNIX time
a DateTime
, senza perdere in precisione, questo è il modo:
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);
}
Da .Net 4.6 e versioni successive, utilizzare DateTimeOffset.Now.ToUnixTimeSeconds ()
Ecco la mia soluzione:
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);
}