Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ protected override async Task<IWebSocket> OnGetTradesWebSocketAsync(Func<KeyValu
{
foreach (var data in parsedMsg["content"]["list"])
{
var exchangeTrade = data.ParseTrade("contQty", "contPrice", "buySellGb", "contDtm", TimestampType.Iso8601UTC, null, typeKeyIsBuyValue: "2");
var exchangeTrade = data.ParseTrade("contQty", "contPrice", "buySellGb", "contDtm", TimestampType.Iso8601Korea, null, typeKeyIsBuyValue: "2");

await callback(new KeyValuePair<string, ExchangeTrade>(parsedMsg["market"].ToStringInvariant(), exchangeTrade));
}
Expand Down
3 changes: 1 addition & 2 deletions src/ExchangeSharp/API/Exchanges/OKGroup/ExchangeOKExAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
51 changes: 39 additions & 12 deletions src/ExchangeSharp/Utility/CryptoUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DateTime> utcNowFunc = UtcNowFuncImpl;
private static Func<DateTime> 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;
Expand Down Expand Up @@ -181,13 +183,19 @@ public static byte[] DecompressDeflate(byte[] bytes)
}
}

public enum SourceTimeZone
{
/// <summary> time zone is specifically specified in string </summary>
AsSpecified,
Local, Korea, UTC
}
/// <summary>
/// Convert object to a UTC DateTime
/// </summary>
/// <param name="obj">Object to convert</param>
/// <param name="defaultValue">Default value if no conversion is possible</param>
/// <returns>DateTime in UTC or defaultValue if no conversion possible</returns>
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)
{
Expand All @@ -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}");
}
}

/// <summary>
/// Convert an object to another type using invariant culture. Consider using the string or DateTime conversions if you are dealing with those types.
Expand Down Expand Up @@ -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<long>());
Expand Down Expand Up @@ -1481,13 +1503,18 @@ public enum TimestampType
UnixSeconds,

/// <summary>
/// ISO 8601 in UTC
/// ISO 8601 in local time
/// </summary>
Iso8601UTC,
Iso8601Local,

/// <summary>
/// ISO 8601 in local time
/// ISO 8601 in Korea Standard Time
/// </summary>
Iso8601Local,
Iso8601Korea,

/// <summary>
/// ISO 8601 in UTC
/// </summary>
Iso8601UTC,
}
}