Convert DateTime to long and also the other way around - c#

I want to store dates as numbers in a table. I know how to do that but I don't know how to go back. How can I cast a long variable to ToDateTime.
DateTime now = DateTime.Now;
long t = now.ToFileTime();
DateTime today = t.ToDateTime; // I am looking for something like this line. This Method does not exist
I know there are many ways of converting DateTime to long. I don't mind which technique to use. I just want to have a way where I can convert back and forth.

To long from DateTime:
long DateTime.Ticks
To DateTime from long:
new DateTime(long)

From long to DateTime: new DateTime(long ticks)
From DateTime to long: DateTime.Ticks

use the pair long t = now.Ticks and DateTime Today = new DateTime(t)

Since you're using ToFileTime, you'll want to use FromFileTime to go the other way. But note:
Ordinarily, the FromFileTime method
restores a DateTime value that was
saved by the ToFileTime method.
However, the two values may differ
under the following conditions:
If the serialization and deserialization of the DateTime value occur in different time zones. For
example, if a DateTime value with a
time of 12:30 P.M. in the U.S. Eastern
Time zone is serialized, and then
deserialized in the U.S. Pacific Time
zone, the original value of 12:30 P.M.
is adjusted to 9:30 A.M. to reflect
the difference between the two time
zones.
If the DateTime value that is serialized represents an invalid time
in the local time zone. In this case,
the ToFileTime method adjusts the
restored DateTime value so that it
represents a valid time in the local
time zone.
If you don't care which long representation of a DateTime is stored, you can use Ticks as others have suggested (Ticks is probably preferable, depending on your requirements, since the value returned by ToFileTime seems to be in the context of the Windows filesystem API).

There are several possibilities (note that the those long values aren't the same as the Unix epoch.
For your example (to reverse ToFileTime()) just use DateTime.FromFileTime(t).

There is a DateTime constructor that takes a long.
DateTime today = new DateTime(t); // where t represents long format of dateTime

long dateTime = DateTime.Now.Ticks;
Console.WriteLine(dateTime);
Console.WriteLine(new DateTime(dateTime));
Console.ReadKey();

If you want to use seconds since 1970 instead of Ticks:
UTC:
long secondsSince1970 = DateTimeOffset.Now.ToUnixTimeSeconds();
Local time:
long secondsSince1970 = DateTime.Now.Ticks / 10000000 - 62135596800;
And back to DateTime
DateTime value = DateTime.MinValue.AddSeconds(secondsSince1970).AddYears(1969);

I will add some additional conversion from string to DateTime to long
string timeString = "2016-08-04";
DateTime date = DateTime.Parse(timeString);
long dateTime = date.Ticks;
And here is the shorthand sort of speak:
long dateTime = DateTime.Parse("2016-08-04").Ticks;
//And for the long to DateTime
DateTime date = new DateTime(dateTime);

Related

DateTimeKind is Unspecified Even Though I Set it

When I check optionDate's DateTime property's DateTimeKind value, I see Unspecified, even though I set dt's DateTimeKind as UTC in below code. I expect optionDate has a DateTime which has a DateTimeKind property set to UTC. Where am I wrong here?
var dt = new DateTime(Convert.ToInt32(optionDateInfo.dateTime.year),
Convert.ToInt32(optionDateInfo.dateTime.month), Convert.ToInt32(optionDateInfo.dateTime.day),
Convert.ToInt32(optionDateInfo.dateTime.hour), Convert.ToInt32(optionDateInfo.dateTime.minutes),
0, DateTimeKind.Utc);
var optionDate = new DateTimeOffset(dt);
This is documented:
DateTimeOffset.DateTime
The value of the DateTime.Kind property of the returned DateTime object is DateTimeKind.Unspecified.
Note that a DateTimeOffset does not have a "kind". It has a date, time, and offset. When you pass your DateTime with kind Utc, to it, it sets its offset to 0, and its date & time to the DateTime given. At this point, your DateTimeKind is "lost".
An offset of 0 does not necessarily mean that its kind is DateTimeKind.Utc. It could be the local time in London, or somewhere in Africa too. So it can't give you a DateTime with kind Utc just because its offset is 0 either.
In addition, DateTime being able to represent 3 kinds of things is already a questionable design, and if the DateTime property can now return 3 different kinds of DateTime depending on whether offset matches the local time, is UTC, or something else, that's just even worse.
Instead, it is designed to have 3 properties that give you DateTimes with different kinds.
DateTime gives you the date & time part of the DateTimeOffset, with kind Unspecified
LocalDateTime converts the date & time part of the DateTimeOffset to the current timezone, and gives you a DateTime with kind Local.
UtcDateTime converts the date & time part of the DateTimeOffset to UTC, and gives you a DateTime with kind Utc.
If you want a DateTime with kind Utc, you should use that last one.
Use the SpecifyKind
var myUtcZeroOffset = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
//If constructing a datetime offset to be not utc you can supply the offset instead
var myOffSetExplicitLocal = new DateTimeOffset(DateTime.Now, new TimeSpan(1, 0, 0));
var localDateTime = myOffSetExplicitLocal.DateTime;
var utcZeroOffSetDateTime = myOffSetExplicitLocal.UtcDateTime;
To make matters worse of cause it is a criticisable implementation from Microsoft, because Universally Coordinated Time is not a timezone but a notation, as per ISO 8601, so in fact toUTC as a concept is flawed because '2021-11-02T10:16:25.12345+01:00' is completely valid in the UTC format and UTC Zero offset, popularily called Zulu being the '2021-11-02T09:16:25.12345Z' equivalent which then gets datetimekind UTC is actually just in coordinated time the zero line around GMT latitude, but what makes it coordinated is the + part which in +00:00 can be abbreviated to Z, so lots of stuff is done to mitigate the inherent conflict and with build servers and cloud providers the .Local is especially dubious, so I would recommend always to persist in ISO 8601 strings instead, unless you actually need to use them in with date operations in Your DB, in said case to name fields appropriate like DateTimeCreatedUtcZero column e.g.
just my five cents of reason on the topic in general, hope it helps.

How to convert a string formatted like 2018-12-27T02:23:29 to Unix Timestamp in C#

I'm assuming I should just parse the string into a DateTime and go from there... But is there a better way of doing this?
You can use the DateTimeOffset struct, which has a ToUnixTimeSeconds (or ToUnixTimeMilliseconds) method you can use:
long unixTimestamp = DateTimeOffset.Parse("2018-12-27T02:23:29").ToUnixTimeSeconds();
If you're curious how it's done, the source is here: https://referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs,8e1e87bf153c720e
You should parse it to a normal DateTime object using something from the DateTime.Parse/ParseExact family of functions, and then call a method like this:
public int ToUnixTime(DateTime d)
{
var epoch = new DateTime(1970,1,1);
return (int)(d - epoch).TotalSeconds;
}
DateTime interally stores the "Ticks" (a invented Time unit) since "12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001), in the Gregorian calendar". As a Int64/Long Number. DateTime thus beats UnixTime easily in possible values. Converting to DateTime should be lossless.
Any ToString() call, any other Property call will simply calculate the values based on those Ticks (and culture/Timezone settings for ToString()). Everything else is just a interpretation of the Tick value.
You should parse to DateTime. And getting from Ticks to something as inprecise as the UnixTime is easy math. See Joels Answer for that.
Do note however the DateTimes preccision and accuaracy do not match fully: https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/ DateTime.Now will usually give you only return values in 18 ms steps. And even the Stopwatch has issues with values < 1 ms.

Convert current local time to any other timezone

I want to test some time-zone related code by comparing local time to UTC. However this test relies on local time being different to UTC and I'm in the UK so 6 months of the year, local time is UTC according to DateTime comparison tests (due to summer time).
I could hard-code my test to convert UTCNow to a certain timezone like EST but on the off-chance my code was used in an American system, now I have the same issue.
So is there a way I can easily convert DateTime.UtcNow to a timezone that's definitely different to my local timezone, without hard-coding it or making assumptions what timezone I'm in?
Ok, as I mentoined in comments, if you want to get timezones which differs from yours, you can do it in that way:
var zone = TimeZoneInfo.GetSystemTimeZones()
.Where(x=>x.BaseUtcOffset != TimeZoneInfo.Local.BaseUtcOffset)
.First();
To convert UTC DateTime to another timezone, you have to use TimeZoneInfo.ConvertTimeFromUtc, sample:
var datetime = // datetime in UTC, for example, DateTime.UtcNow
var zone = // target zone
return TimeZoneInfo.ConvertTimeFromUtc(datetime, zone);
You can check samples in my pet project here
Time zones in .net are a very confusing matter. DateTime only supports local and UTC timezones really, it has no concept of different zones as it only gets the current offset from the machine and applies it to a tick count value which is in UTC.
So at a first there's no way to change to another timezone, but you can simulate something. If you want per example simulate a timezone GMT+2, you must first retrieve the current zone offset and add the difference of this offset and the desired offset to the local date, something like this:
TimeSpan targetOffset = new TimeSpan(2, 0, 0) - TimeZoneInfo.Local.BaseUtcOffset; //target to GMT+2
DateTime targetNow = DateTime.Now + targetOffset;
In this way the Date will have the values like if it were on that timezone, but for calculations using the datetime object and not just the year/month/day/hour/minute/second all of them will be wrong as the object will be marked as local and thus will have the wrong values.
To solve this you have two options, reverse your logic (convert non-local time to local time) or just work with UTC dates.
The first approach is very easy:
DateTime nonLocal = new DateTime(2016, 10, 21, 13, 33, 0); //We suppose we want 2016-10-21 13:33:00 at GMT+2
DateTime local = nonLocal + (TimeZoneInfo.Local.BaseUtcOffset - new TimeSpan(2, 0, 0));
This will yield to correct DateTime operations, but, here we go again with problems, if you use the year/month/day/hour/minute they will be in your local zone, not in the supposed zone and code using these properties will fail.
Finally, the best approach is the second one, you just forget about timezones and whenever you get a DateTime you convert it to UTC, all will work flawlesly and when you need to represent the data just convert it to local and all is done, no need to worry about DateTime arithmetic or properties differing just because they're on another timezone.
public static class DateTimeExtensions
{
public static DateTime As(this DateTime source, string timeZoneName)
{
DateTime utcTime = DateTime.SpecifyKind(source, DateTimeKind.Unspecified);
TimeZoneInfo newTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
return TimeZoneInfo.ConvertTimeFromUtc(utcTime, newTimeZone);
}
}
Usage:
DateTime date1 = DateTime.UtcNow;
DateTime date2 = date1.As("Eastern Standard Time");

How to convert UTC+0 Date to PST Date?

I have this UTC+0 Date :
2011-11-28T07:21:41.000Z
and I'd like, on C#, convert it to a PST Date. How can I do it? Tried with :
object.Data.ToLocalTime()
but I can't get the correct value (which should be 2011-11-27)
EDIT
Also tried (after suggesion on another topic) this :
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(object.Data.ToShortDateString()),
DateTimeKind.Utc);
DateTime dt = convertedDate.ToLocalTime();
string dataVideo = dt.ToShortDateString();
but the date still 28/11/2011, not 27/11/2011
I've changed my clock to use UTC-08:00 Pacific Time.
DateTime timestamp = DateTime.Parse("2011-11-28T07:21:41.000Z");
Console.WriteLine("UTC: " + timestamp.ToUniversalTime());
Console.WriteLine("PST: " + timestamp.ToLocalTime());
Output:
UTC: 28/11/2011 7:21:41
PST: 27/11/2011 23:21:41
Example with TimeZoneInfo
DateTime timestamp = DateTime.Parse("2011-11-28T07:21:41.000Z");
Console.WriteLine("UTC: " + timestamp.ToUniversalTime());
Console.WriteLine("GMT+1: " + timestamp.ToLocalTime());
Console.WriteLine("PST: " + TimeZoneInfo.ConvertTimeBySystemTimeZoneId(timestamp, "Pacific Standard Time"));
Output:
UTC: 28/11/2011 7:21:41
GMT+1: 28/11/2011 8:21:41
PST: 27/11/2011 23:21:41
For a little more color
2011-11-28T07:21:41.000Z
This is a ISO8601 Timestamp, the Z at the end stands for UTC. This represents a specific instance in time.
DateTime.Parse will return to you a local date time structure, there are three types of datetime kinds, UTC, Local, and Unspecified.
If you try displaying this, it will show you this instant in your computers current timezone (I'm eastern time so when I print it I get 11/28/2011 2:21:41 AM).
If I want to switch this DateTime Kind to UTC, I could do something like
DateTime.Parse("2011-11-28T07:21:41.000Z").ToUniversalTime()
Printing this now (since it's kind is now UTC) I get 11/28/2011 7:21:41 AM.
Note that although the time is printed differently both these date times are referring to the same instant in time.
To display this instant in a different timezone, the easiest way imo is the TimeZoneInfo class (though I'm not sure it's 100% accurate).
TimeZoneInfo.ConverTimeBySystemTimeZoneId(dateTime, "Pacific Standard Time").
Printing it now will yield your desired result 11/27/2011 11:21:41 PM
Note that this return DateTime's Kind property is now Unspecified, meaning you won't be able to transfer it back to UTC without more information. You no longer have a specific instant in time, rather you have a unspecified time..we know it's the same instant as the ones previously just in pacific time, but the computer no longer knows that. Keep that in mind if you want to store this time.

Is there any function for UTC to convert to particular datetime to UTC date time

I want to convert for example a particular date 12-11-2008 11:33:04.510 to UTC datetime. Can anyone help me how to do this. I want to do this in c# coding.
Just use DateTime.ToUniversalTime, assuming it's in the local timezone of your computer at the moment.
DateTime is not timezone-aware. It can be treated as local time or UTC time, and as Jon Skeet said, DateTime.ToUniversalTime can convert between them.
In .NET3.5 there is also the TimeZoneInfo class which allows for conversion of DateTime's between arbitrary timezones, but for your needs, the former is probably good enough.
There's also a DateTimeOffset class which works just like a DateTime, except it also stores an offset from UTC, making it a bit more robust if you have to handle multiple timezones.
If you want the DateTime to be identified as a UTC, you can also assign it a DateTimeKind,
DateTime saveNow = DateTime.Now;
DateTime myDt;
myDt = DateTime.SpecifyKind(saveNow, DateTimeKind.Utc);
Or if you know it's local:
string formattedDate = "12-11-2008 11:33:04.510";
DateTime localDt = DateTime.Parse(formattedDate, null,
DateTimeStyles.AssumeLocal);
Or if you know it's UTC:
string formattedDate = "12-11-2008 11:33:04.510";
DateTime localDt = DateTime.Parse(formattedDate, null,
DateTimeStyles.AssumeUniversal);

Categories

Resources