diff --git a/src/ExchangeSharp/API/Exchanges/Bithumb/ExchangeBithumbAPI.cs b/src/ExchangeSharp/API/Exchanges/Bithumb/ExchangeBithumbAPI.cs index d8247fc6..ebfce788 100644 --- a/src/ExchangeSharp/API/Exchanges/Bithumb/ExchangeBithumbAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/Bithumb/ExchangeBithumbAPI.cs @@ -212,7 +212,7 @@ protected override async Task OnGetTradesWebSocketAsync(Func(parsedMsg["market"].ToStringInvariant(), exchangeTrade)); } diff --git a/src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs b/src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs index f02e84f0..371479bb 100644 --- a/src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs @@ -359,8 +359,7 @@ protected override async Task ProcessRequestAsync(IHttpWebRequest request, Dicti payload.Remove("nonce"); var method = request.Method; - var now = DateTime.Now; - var timeStamp = TimeZoneInfo.ConvertTimeToUtc(now).ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); + var timeStamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); var requestUrl = request.RequestUri.PathAndQuery; var body = payload.Any() ? JsonConvert.SerializeObject(payload) : string.Empty; diff --git a/src/ExchangeSharp/Utility/CryptoUtility.cs b/src/ExchangeSharp/Utility/CryptoUtility.cs index 0869f80f..ed55b0a5 100644 --- a/src/ExchangeSharp/Utility/CryptoUtility.cs +++ b/src/ExchangeSharp/Utility/CryptoUtility.cs @@ -37,10 +37,12 @@ public static class CryptoUtility internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); internal static readonly DateTime UnixEpochLocal = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local); internal static readonly Encoding Utf8EncodingNoPrefix = new UTF8Encoding(false, true); + static string koreanZoneId = "Korea Standard Time"; + static TimeZoneInfo koreaZone = TimeZoneInfo.FindSystemTimeZoneById(koreanZoneId); - private static Func utcNowFunc = UtcNowFuncImpl; + private static Func utcNowFunc = UtcNowFuncImpl; - private static DateTime UtcNowFuncImpl() + private static DateTime UtcNowFuncImpl() { // this is the only place in the code that DateTime.UtcNow is allowed. DateTime.UtcNow and DateTime.Now should not exist anywhere else in the code. return DateTime.UtcNow; @@ -181,13 +183,19 @@ public static byte[] DecompressDeflate(byte[] bytes) } } + public enum SourceTimeZone + { + /// time zone is specifically specified in string + AsSpecified, + Local, Korea, UTC + } /// /// Convert object to a UTC DateTime /// /// Object to convert /// Default value if no conversion is possible /// DateTime in UTC or defaultValue if no conversion possible - public static DateTime ToDateTimeInvariant(this object obj, bool isSourceObjUTC = true, DateTime defaultValue = default) + public static DateTime ToDateTimeInvariant(this object obj, SourceTimeZone sourceTimeZone = SourceTimeZone.UTC, DateTime defaultValue = default) { if (obj == null) { @@ -200,9 +208,20 @@ public static DateTime ToDateTimeInvariant(this object obj, bool isSourceObjUTC return defaultValue; } DateTime dt = (DateTime)Convert.ChangeType(jValue == null ? obj : jValue.Value, typeof(DateTime), CultureInfo.InvariantCulture); - if (dt.Kind == DateTimeKind.Utc || isSourceObjUTC) return dt; - else return dt.ToUniversalTime(); // convert to UTC - } + switch (sourceTimeZone) + { + case SourceTimeZone.AsSpecified: + throw new NotImplementedException(); // TODO: implement this when needed + case SourceTimeZone.Local: + return DateTime.SpecifyKind(dt, DateTimeKind.Local).ToUniversalTime(); // convert to UTC + case SourceTimeZone.Korea: + return TimeZoneInfo.ConvertTime(dt, koreaZone, TimeZoneInfo.Utc); // convert to UTC + case SourceTimeZone.UTC: + return DateTime.SpecifyKind(dt, DateTimeKind.Utc); + default: + throw new NotImplementedException($"Unexpected {nameof(sourceTimeZone)}: {sourceTimeZone}"); + } + } /// /// Convert an object to another type using invariant culture. Consider using the string or DateTime conversions if you are dealing with those types. @@ -698,10 +717,13 @@ public static DateTime ParseTimestamp(object value, TimestampType type) switch (type) { case TimestampType.Iso8601Local: - return value.ToDateTimeInvariant(false); + return value.ToDateTimeInvariant(SourceTimeZone.Local); + + case TimestampType.Iso8601Korea: + return value.ToDateTimeInvariant(SourceTimeZone.Korea); case TimestampType.Iso8601UTC: - return value.ToDateTimeInvariant(true); + return value.ToDateTimeInvariant(SourceTimeZone.UTC); case TimestampType.UnixNanoseconds: return UnixTimeStampToDateTimeNanoseconds(value.ConvertInvariant()); @@ -1481,13 +1503,18 @@ public enum TimestampType UnixSeconds, /// - /// ISO 8601 in UTC + /// ISO 8601 in local time /// - Iso8601UTC, + Iso8601Local, /// - /// ISO 8601 in local time + /// ISO 8601 in Korea Standard Time /// - Iso8601Local, + Iso8601Korea, + + /// + /// ISO 8601 in UTC + /// + Iso8601UTC, } }