mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-16 19:03:01 +00:00
690f2a63e5
commit 90f285d7f6bcd926ce9ca3d5832b1d70a5eae6ab Author: JKorf <jankorf91@gmail.com> Date: Sun Jun 25 19:51:12 2023 +0200 Docs commit 72187035c703d1402b37bd2f4c3e066706f28d67 Author: JKorf <jankorf91@gmail.com> Date: Sat Jun 24 16:02:53 2023 +0200 docs commit 8411977292f1fb0b6e0705b1ad675b79a5311d90 Author: JKorf <jankorf91@gmail.com> Date: Fri Jun 23 18:25:15 2023 +0200 wip commit cb7d33aad5d2751104c8b8a6c6eadbf0d36b672c Author: JKorf <jankorf91@gmail.com> Date: Fri Jun 2 19:26:26 2023 +0200 wip commit 4359a2d05ea1141cff516dab18f364a6ca854e18 Author: JKorf <jankorf91@gmail.com> Date: Wed May 31 20:51:36 2023 +0200 wip commit c6adb1b2f728d143f6bd667139c619581122a3c9 Author: JKorf <jankorf91@gmail.com> Date: Mon May 1 21:13:47 2023 +0200 wip commit 7fee733f82fa6ff574030452f0955c9e817647dd Author: JKorf <jankorf91@gmail.com> Date: Thu Apr 27 13:02:56 2023 +0200 wip commit f8057313ffc9b0c31effcda71d35d105ea390971 Author: JKorf <jankorf91@gmail.com> Date: Mon Apr 17 21:37:51 2023 +0200 wip
199 lines
9.3 KiB
C#
199 lines
9.3 KiB
C#
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
|
|
namespace CryptoExchange.Net.Converters
|
|
{
|
|
/// <summary>
|
|
/// Datetime converter. Supports converting from string/long/double to DateTime and back. Numbers are assumed to be the time since 1970-01-01.
|
|
/// </summary>
|
|
public class DateTimeConverter: JsonConverter
|
|
{
|
|
private static readonly DateTime _epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
|
private const long _ticksPerSecond = TimeSpan.TicksPerMillisecond * 1000;
|
|
private const decimal _ticksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000;
|
|
private const decimal _ticksPerNanosecond = TimeSpan.TicksPerMillisecond / 1000m / 1000;
|
|
|
|
/// <inheritdoc />
|
|
public override bool CanConvert(Type objectType)
|
|
{
|
|
return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
|
{
|
|
if (reader.Value == null)
|
|
return null;
|
|
|
|
if(reader.TokenType is JsonToken.Integer)
|
|
{
|
|
var longValue = (long)reader.Value;
|
|
if (longValue == 0 || longValue == -1)
|
|
return objectType == typeof(DateTime) ? default(DateTime): null;
|
|
if (longValue < 19999999999)
|
|
return ConvertFromSeconds(longValue);
|
|
if (longValue < 19999999999999)
|
|
return ConvertFromMilliseconds(longValue);
|
|
if (longValue < 19999999999999999)
|
|
return ConvertFromMicroseconds(longValue);
|
|
|
|
return ConvertFromNanoseconds(longValue);
|
|
}
|
|
else if (reader.TokenType is JsonToken.Float)
|
|
{
|
|
var doubleValue = (double)reader.Value;
|
|
if (doubleValue == 0 || doubleValue == -1)
|
|
return objectType == typeof(DateTime) ? default(DateTime) : null;
|
|
|
|
if (doubleValue < 19999999999)
|
|
return ConvertFromSeconds(doubleValue);
|
|
|
|
return ConvertFromMilliseconds(doubleValue);
|
|
}
|
|
else if(reader.TokenType is JsonToken.String)
|
|
{
|
|
var stringValue = (string)reader.Value;
|
|
if (string.IsNullOrWhiteSpace(stringValue))
|
|
return null;
|
|
|
|
if (string.IsNullOrWhiteSpace(stringValue) || stringValue == "0" || stringValue == "-1")
|
|
return objectType == typeof(DateTime) ? default(DateTime) : null;
|
|
|
|
if (stringValue.Length == 8)
|
|
{
|
|
// Parse 20211103 format
|
|
if (!int.TryParse(stringValue.Substring(0, 4), out var year)
|
|
|| !int.TryParse(stringValue.Substring(4, 2), out var month)
|
|
|| !int.TryParse(stringValue.Substring(6, 2), out var day))
|
|
{
|
|
Trace.WriteLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | Warning | Unknown DateTime format: " + reader.Value);
|
|
return default;
|
|
}
|
|
return new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Utc);
|
|
}
|
|
|
|
if (stringValue.Length == 6)
|
|
{
|
|
// Parse 211103 format
|
|
if (!int.TryParse(stringValue.Substring(0, 2), out var year)
|
|
|| !int.TryParse(stringValue.Substring(2, 2), out var month)
|
|
|| !int.TryParse(stringValue.Substring(4, 2), out var day))
|
|
{
|
|
Trace.WriteLine("{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | Warning | Unknown DateTime format: " + reader.Value);
|
|
return default;
|
|
}
|
|
return new DateTime(year + 2000, month, day, 0, 0, 0, DateTimeKind.Utc);
|
|
}
|
|
|
|
if (double.TryParse(stringValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var doubleValue))
|
|
{
|
|
// Parse 1637745563.000 format
|
|
if (doubleValue < 19999999999)
|
|
return ConvertFromSeconds(doubleValue);
|
|
if (doubleValue < 19999999999999)
|
|
return ConvertFromMilliseconds((long)doubleValue);
|
|
if (doubleValue < 19999999999999999)
|
|
return ConvertFromMicroseconds((long)doubleValue);
|
|
|
|
return ConvertFromNanoseconds((long)doubleValue);
|
|
}
|
|
|
|
if(stringValue.Length == 10)
|
|
{
|
|
// Parse 2021-11-03 format
|
|
var values = stringValue.Split('-');
|
|
if(!int.TryParse(values[0], out var year)
|
|
|| !int.TryParse(values[1], out var month)
|
|
|| !int.TryParse(values[2], out var day))
|
|
{
|
|
Trace.WriteLine("{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | Warning | Unknown DateTime format: " + reader.Value);
|
|
return default;
|
|
}
|
|
|
|
return new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Utc);
|
|
}
|
|
|
|
return DateTime.Parse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
|
|
}
|
|
else if(reader.TokenType == JsonToken.Date)
|
|
{
|
|
return (DateTime)reader.Value;
|
|
}
|
|
else
|
|
{
|
|
Trace.WriteLine("{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff} | Warning | Unknown DateTime format: " + reader.Value);
|
|
return default;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a seconds since epoch (01-01-1970) value to DateTime
|
|
/// </summary>
|
|
/// <param name="seconds"></param>
|
|
/// <returns></returns>
|
|
public static DateTime ConvertFromSeconds(double seconds) => _epoch.AddTicks((long)Math.Round(seconds * _ticksPerSecond));
|
|
/// <summary>
|
|
/// Convert a milliseconds since epoch (01-01-1970) value to DateTime
|
|
/// </summary>
|
|
/// <param name="milliseconds"></param>
|
|
/// <returns></returns>
|
|
public static DateTime ConvertFromMilliseconds(double milliseconds) => _epoch.AddTicks((long)Math.Round(milliseconds * TimeSpan.TicksPerMillisecond));
|
|
/// <summary>
|
|
/// Convert a microseconds since epoch (01-01-1970) value to DateTime
|
|
/// </summary>
|
|
/// <param name="microseconds"></param>
|
|
/// <returns></returns>
|
|
public static DateTime ConvertFromMicroseconds(long microseconds) => _epoch.AddTicks((long)Math.Round(microseconds * _ticksPerMicrosecond));
|
|
/// <summary>
|
|
/// Convert a nanoseconds since epoch (01-01-1970) value to DateTime
|
|
/// </summary>
|
|
/// <param name="nanoseconds"></param>
|
|
/// <returns></returns>
|
|
public static DateTime ConvertFromNanoseconds(long nanoseconds) => _epoch.AddTicks((long)Math.Round(nanoseconds * _ticksPerNanosecond));
|
|
/// <summary>
|
|
/// Convert a DateTime value to seconds since epoch (01-01-1970) value
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
[return: NotNullIfNotNull("time")]
|
|
public static long? ConvertToSeconds(DateTime? time) => time == null ? null: (long)Math.Round((time.Value - _epoch).TotalSeconds);
|
|
/// <summary>
|
|
/// Convert a DateTime value to milliseconds since epoch (01-01-1970) value
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
[return: NotNullIfNotNull("time")]
|
|
public static long? ConvertToMilliseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).TotalMilliseconds);
|
|
/// <summary>
|
|
/// Convert a DateTime value to microseconds since epoch (01-01-1970) value
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
[return: NotNullIfNotNull("time")]
|
|
public static long? ConvertToMicroseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerMicrosecond);
|
|
/// <summary>
|
|
/// Convert a DateTime value to nanoseconds since epoch (01-01-1970) value
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <returns></returns>
|
|
[return: NotNullIfNotNull("time")]
|
|
public static long? ConvertToNanoseconds(DateTime? time) => time == null ? null : (long)Math.Round((time.Value - _epoch).Ticks / _ticksPerNanosecond);
|
|
|
|
|
|
/// <inheritdoc />
|
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
|
{
|
|
var datetimeValue = (DateTime?)value;
|
|
if (datetimeValue == null)
|
|
writer.WriteValue((DateTime?)null);
|
|
if(datetimeValue == default(DateTime))
|
|
writer.WriteValue((DateTime?)null);
|
|
else
|
|
writer.WriteValue((long)Math.Round(((DateTime)value! - new DateTime(1970, 1, 1)).TotalMilliseconds));
|
|
}
|
|
}
|
|
}
|