Computing milliseconds since 1970 in C# yields different date than JavaScript - c#

I need to compute the JavaScript getTime method in C#.
For simplicity, I chose a fixed date in UTC and compared the C#:
C#
DateTime e = new DateTime(2011, 12, 31, 0, 0, 0, DateTimeKind.Utc);
DateTime s = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan t = (e - s);
var x = t.TotalMilliseconds.ToString();
=> 1325289600000
and the JavaScript results:
JavaScript
var d = new Date(2011, 12, 31, 0, 0, 0)
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds());
utcDate.getTime()
=> 1327960800000
Any hints on what I'm doing wrong?
Thanks!

Javascript months are zero-based.
12 means January of next year.
You want 11.

If you meant for the input to be at UTC, you should be doing this instead:
var ts = Date.UTC(2011,11,31,0,0,0);
As SLaks pointed out, months run 0-11, but even then - you must initialize the date as UTC if you want the response in UTC. In your code, you were initializing a local date, and then converting it to UTC. The result would be different depending on the time zone of the computer where the code is running. With Date.UTC, you get back a timestamp - not a Date object, and it will be the same result regardless of where it runs.
From Chrome's debugging console:
This is the same value returned from your .NET code, which looks just fine, except I would return a long, not a string.

The date JS is wrong I believe. Omit the var utcDate line and output just d.getTime()
The time between two dates is the same, regardless of timezone and offset. Timezones are relative to an ACTUAL point in time, so whether you call .getTime() on the UTC or EST or PST date, it will be the same relative to 1970-1-1 of the same timezone.
2011-12-31 EST - 1970-1-1 EST
== 2011-12-31 PST - 1970-1-1 PST
== 2011-12-31 UTC - 1970-1-1 UTC
EDIT: Per #Slaks above, you also are not using the 0-based month (which I also had no idea about).

Related

C# converting to and from Unix time - 1 day lost

here is the code:
var date = DateTime.Now.Date;
var ms = (long)(date - DateTimeOffset.UnixEpoch).TotalMilliseconds;
var date1 = DateTimeOffset.FromUnixTimeMilliseconds(ms).DateTime.Date;
date is 24th and date1 is 23rd
why dont they match?
Use DateTimeOffset.FromUnixTimeMilliseconds(ms).LocalDateTime.
DateTime.Now has Kind = Local so it is eskewing your UTC offset.
You can see it with:
var kind = DateTime.Now.Date.Kind;
and then you can make a small test with the "kind":
var date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
var ms = (long)(date - DateTimeOffset.UnixEpoch).TotalMilliseconds;
How much ms is? Depending on winter/summer time and your location, it probably isn't 0.
So your ms includes your UTC offset. Now you have to:
var date1 = DateTimeOffset.FromUnixTimeMilliseconds(ms).LocalDateTime;
and let's hope you are still in the "original" utc offset (so not enough days have passed between the calculation of date and the calculation of date1 for you to switch between winter/summer time)
(if you did everything correctly, you don't really need the .Date after .LocalDateTime, because the date should already be 00:00:00)

C# - Handling ranges of prevailing times on DST transition days - The supplied DateTime represents an invalid time

A couple of premises:
By "prevailing time" I mean how it is handled locally (my industry uses this terminology). For example, Eastern Prevailing Time has a UTC offset of -05:00 except during DST when it is -04:00
I find it much cleaner to handle range data by treating the end value as exclusive, rather than the hackish inclusive approach (where you have to subtract an epsilon from the first value beyond the end of your range).
For example, the range of values from 0 (inclusive) to 1 (exclusive), as per interval notation, is [0, 1), which is much more readable than [0, 0.99999999999...] (and is less prone to rounding issues and thus off-by-one errors, because the epsilon value depends on the data type being used).
With these two ideas in mind, how can I represent the final hour time range on the spring DST transition day, when the ending timestamp is invalid (i.e. there is no 2am, it instantly becomes 3am)?
[2019-03-10 01:00, 2019-03-10 02:00) in your time zone of choice that supports DST.
Putting the end time as 03:00 is quite misleading, as it looks like a 2-hour wide time range.
When I run it through this C# sample code, it blows up:
DateTime hourEnd_tz = new DateTime(2019, 3, 10, 0, 0, 0, DateTimeKind.Unspecified);//midnight on the spring DST transition day
hourEnd_tz = hourEnd_tz.AddHours(2);//other code variably computes this offset from business logic
TimeZoneInfo EPT = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");//includes DST rules
DateTime hourEnd_utc = TimeZoneInfo.ConvertTime(//interpret the value from the user's time zone
hourEnd_tz,
EPT,
TimeZoneInfo.Utc);
System.ArgumentException: 'The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid.
Parameter name: dateTime'
How might I handle this case (elsewhere I am already handling the autumn ambiguous times), without having to extensively refactor my time range class library?
Premise 1 is reasonable, though often the word "prevailing" is dropped and it's just called "Eastern Time" - either are fine.
Premise 2 is a best practice. Half-open ranges offer many benefits, such as not having to deal with date math involving an epsilon, or having to determine what precision the epsilon should have.
However, the range you're attempting to describe cannot be done with a date and time alone. It needs to also involve the offset from UTC. For US Eastern Time (using ISO 8601 format), it looks like this:
[2019-03-10T01:00:00-05:00, 2019-03-10T03:00:00-04:00) (spring-forward)
[2019-11-03T02:00:00-04:00, 2019-11-03T02:00:00-05:00) (fall-back)
You said:
Putting the end time as 03:00 is quite misleading, as it looks like a 2-hour wide time range.
Ah, but putting the spring end time as 02:00 would also be misleading, as that local time is not observed on that day. Only by combining the actual local date and time with the offset at that time can one be accurate.
You can use the DateTimeOffset structure in .NET to model these (or the OffsetDateTime structure in Noda Time).
How might I handle this case ... without having to extensively refactor my time range class library?
First, you'll need an extension method that lets you convert from DateTime to a DateTimeOffset for a specific time zone. You'll need this for two reasons:
The new DateTimeOffset(DateTime) constructor assumes that a DateTime with Kind of DateTimeKind.Unspecified should be treated as local time. There's no opportunity to specify a time zone.
The new DateTimeOffset(dt, TimeZoneInfo.GetUtcOffset(dt)) approach isn't good enough, because GetUtcOffset presumes you want the standard time offset in the case of ambiguity or invalidity. That is usually not the case, and thus you have to code the following yourself:
public static DateTimeOffset ToDateTimeOffset(this DateTime dt, TimeZoneInfo tz)
{
if (dt.Kind != DateTimeKind.Unspecified)
{
// Handle UTC or Local kinds (regular and hidden 4th kind)
DateTimeOffset dto = new DateTimeOffset(dt.ToUniversalTime(), TimeSpan.Zero);
return TimeZoneInfo.ConvertTime(dto, tz);
}
if (tz.IsAmbiguousTime(dt))
{
// Prefer the daylight offset, because it comes first sequentially (1:30 ET becomes 1:30 EDT)
TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
TimeSpan offset = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
return new DateTimeOffset(dt, offset);
}
if (tz.IsInvalidTime(dt))
{
// Advance by the gap, and return with the daylight offset (2:30 ET becomes 3:30 EDT)
TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
TimeSpan gap = offsets[1] - offsets[0];
return new DateTimeOffset(dt.Add(gap), offsets[1]);
}
// Simple case
return new DateTimeOffset(dt, tz.GetUtcOffset(dt));
}
Now that you have that defined (and put it in a static class somewhere in your project), you can call it where needed in your application.
For example:
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = new DateTime(2019, 3, 10, 2, 0, 0, DateTimeKind.Unspecified);
DateTimeOffset dto = dt.ToDateTimeOffset(tz); // 2019-03-10T03:00:00-04:00
or
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = new DateTime(2019, 11, 3, 1, 0, 0, DateTimeKind.Unspecified);
DateTimeOffset dto = dt.ToDateTimeOffset(tz); // 2019-11-03T01:00:00-04:00
or
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = new DateTime(2019, 3, 10, 0, 0, 0, DateTimeKind.Unspecified);
DateTimeOffset midnight = dt.ToDateTimeOffset(tz); // 2019-03-10T00:00:00-05:00
DateTimeOffset oneOClock = midnight.AddHours(1); // 2019-03-10T01:00:00-05:00
DateTimeOffset twoOClock = oneOClock.AddHours(1); // 2019-03-10T02:00:00-05:00
DateTimeOffset threeOClock = TimeZoneInfo.ConvertTime(twoOClock, tz); // 2019-03-10T03:00:00-04:00
TimeSpan diff = threeOClock - oneOClock; // 1 hour
Note that subtracting two DateTimeOffset values correctly considers their offsets (whereas subtracting two DateTime values completely ignores their Kind).

Get shortTimeDate from Unix format (C#)

I have time input data as below:
1536271200
1536184800
1536098400
1536012000
1535925600
I made quick Unix TimeConverter:
public static DateTime Converter(double ts)
{
DateTime org= new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
org = org.AddSeconds(ts);
org = org.ToLocalTime();
return org;
}
but after convert it return me date as below:
2018-09-10 00:00:00
2018-09-07 00:00:00
2018-09-06 00:00:00
2018-09-05 00:00:00
2018-09-04 00:00:00
2018-09-03 00:00:00
How to get shortDateFormat (YYYY-MM-DD)?
You can use .ToString(format) to get what ever format you want, and in this case it would be .ToString("yyyy-MM-dd"):
public static string Converter(double ts)
{
DateTime org= new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
org = org.AddSeconds(ts);
org = org.ToLocalTime();
return org.ToString("yyyy-MM-dd");
}
and of course the function's return type must be string.
You're getting confused between a DateTime object, and a "text string that looks like a date"
Your DateTime object holds the instant in time that the date is. You can make it into a text string that looks like whatever you want by using .ToString() and a format string:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
Or you can use one of the provided shortcut methods for standard format strings, like .ToShortDateString()
https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=netframework-4.7.2
Ultimately, what you need to appreciate is that you're complaining "my date has a time tacked on the end" -> datetimes always have a time component. There is no date in this world, your birthday, your grad day, new year's day etc that does NOT have a time associated with it.
Everything happens at a time, on a date.
When you told your program to print those dates out to the console, it included the times (all midnight) because that's what your system does by default. If you want to print them out without the times, specify a format that doesn't include time placeholders.. It is in the process of preparing data for display, that we choose what we want to see

What are valid UTCDateTime type string formats for AIF transfomrmations?

Im am trying to write a .net class that transforms a piece of xml to a AX UtcDateTime type.
The class is used in an inbound transformation.
Original xml:
<DateTime>
<Date>2014-06-12</Date>
<Time>10:52:00</Time>
<Zone>+02:00</Zone>
</DateTime>
My resulting xml leads to an exeption in the exeptionlog:
"The value '2014-06-12T12:52:00+02:00' is not a valid UtcDateTime type."
I think AIF expect the Z at the end of the value, and I am not sure if the localDateTime is mandatory and or if the milliseconds are a requirement.
I would like to know how the UtcDateTime field in transformed xml should be formatted to be accepted by AIF.
Like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00+02:00">2014-06-12T08:52:00Z</MessageHeaderDateTime>
or like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00.1108723+02:00">2014-06-12T08:52:00.1108723Z</MessageHeaderDateTime>
or are other things missing?
My Code
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc);
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
DateTime netdttmoffset = netdttm.Subtract(timespan);
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
datetime.localDateTimeSpecified = true;
I use a similar appraoch for the case where I use utcnow.
Problem i that I have limited testing possibilities due to hot-swapping being disbled in the environment where I have to develop my code. So I would like to be certainin about the formatting.
Thanx for your help.
I finally got it to work. My solution:
//declare the AX utcdatetime type from the cs class generate with:
//xsd C:\...\SharedTypes.xsd C:\..\AIFschema.xsd /Classes /Out:C:\location\of\csfile\
AxType_DateTime datetime = new AxType_DateTime();
//Ax store the time in GMT with an optional local time. My XML can have any timezone.
datetime.timezone = AxdEnum_Timezone.GMT_COORDINATEDUNIVERSALTIME;
//I set this to false as i am not interested in actually storing the local time. Plus AX fails over the formatting .net returns.
datetime.timezoneSpecified = false;
//{... left out code to retrieve the hours, minutes etc from my XML}
//declare the .net datetime variable with the values from the xml:
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc);
DateTime netdttmoffset = new DateTime();
// (optional field) <zone>+01:00</zone>
if (message.Header.DateTime.Zone != null)
{
{... left out code to retrive zone offset info from xml}
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
netdttmoffset = netdttm.Subtract(timespan);
}
else //no zone, so datetime == GMT datetime.
{
netdttmoffset = netdttm;
}
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
//do not output to xml, or AX will fail over this.
datetime.localDateTimeSpecified = false;
Result xml snippet as accepted by AX:
<MessageHeaderDateTime>2014-07-30T16:41:10.001Z</MessageHeaderDateTime>
I found this to be easier. If you want a particular datetime, say Jan 31, 2015 8:00 am, to be stored in AX, the .net code to make it happen would be
DateTime utcDateTime = new DateTime(2015, 1, 31, 8, 0, 0).ToUniversalTime();
var workerStartDate = new AxdExtType_HcmEmploymentStartDateTime
{
Value = utcDateTime
};
The XML generated would be would be <WorkerStartDate>2015-05-12T13:00:00Z</WorkerStartDate>, assuming you are 5 hours behind GMT on the computer that runs the .net code. The AX database will store the value 2015-05-12T13:00:00Z as well.
<dyn:StartDate>2014-06-22T00:00:00.000+02:00</dyn:StartDate>
This format always does the trick for me. (Notice the ms)

DateTime format with REST and json

I'm having a huge problem trying to figure out a json response from a REST endpoint I'm getting information from.
The date that is coming back looks like this 1319068800000
if I attempt to convert this value like so:
DateTime currentServerTime = DateTime.FromFileTimeUtc(1319068800000);
I get this output: 1/2/1601 12:38:26 PM ...obviously wrong :(
The REST endpoint I'm using has a cool HTML display of the json response, and their format of the same value looks like this: 2011/10/20 00:00:00 UTC
Can someone please shed some light on this for me? I'm trying to update the date through this REST API and when I send a date using this code
DateTime.Now.ToFileTimeUtc().ToString();
I get this result 129691518811163201, and when I send this to the API it bombs out saying I have an valid date. Thanks!
Both #Bill and #Christofer are right. You still need to convert the Unix time to a DateTime, though. Here's a small function that does this: Convert a Unix timestamp to a .NET DateTime
Code quoted from the site (by Simone Chiaretta):
static DateTime ConvertFromUnixTimestamp(double timestamp)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}
static double ConvertToUnixTimestamp(DateTime date)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan diff = date - origin;
return Math.Floor(diff.TotalSeconds);
}
It looks like the number of milliseconds since Jan 1, 1970 12:00 am GMT. This is the internal timestamp format that is typically used in Java.
user=> (java.util.Date. 1319068800000)
Date Wed Oct 19 20:00:00 EDT 2011
You can divide the returned number with 1000 before converting it to a DateTime. It seems to be returned as milliseconds since Unix epoch.

Categories

Resources