Converting ticks to DateTime - c#

There are a number of questions on this site explaining how to do this. My problem I when I do what seems to work for everyone else I don't get the correct date or time. The code is ...
long numberOfTicks = Convert.ToInt64(callAttribute);
startDateTime = new DateTime(numberOfTicks);
The value of callAttribute is = "1379953111"
After converting it the value of numberOfTicks = 1379953111
But the DateTime ends up being startDateTime = {1/1/0001 12:02:17 AM}
I have taken the same value for ticks and converted it online and it comes up with the correct date/time.
What am I doing wrong?

Your value doesn't seem to be a number of ticks; I suspect it's a UNIX timestamp (number of seconds since 1970/01/01 UTC)
Here's a function to convert from a UNIX timestamp:
static readonly DateTime _unixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime DateFromTimestamp(long timestamp)
{
return _unixEpoch.AddSeconds(timestamp);
}

Related

How can i translate string timestamp to Date?

I has in string format, timestamp 1593339378252, i need convert this, to a normal human date-20.06.2020
I try this code
var timestamp = Convert.ToInt64(dateFrom);
// Format our new DateTime object to start at the UNIX Epoch
System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
// Add the timestamp (number of seconds since the Epoch) to be converted
dateTime = dateTime.AddSeconds(timestamp);
but if i try convert to int32,16,64 i get System.ArgumentOutOfRangeException
It seems that your timestamp actually contains number of milliseconds, not seconds:
new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc).AddMilliseconds(1593339378252)
// on my machine - 28-Jun-20 10:16:18 AM
You can use var dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(yourValue);
For more information, also look at the documentation

C# Get specific Date in ToInt64(milliseconds)

I just cannot figure this out....Damnit! Please see the calling method in the second code snippet. You'll see a commented out line that reads //_time = time.ToUTCString(); Go to the first code snippet to see the method ToUTCString(). You can see that it takes the datetime, converts it to Universal Time and subtracts the UnixEpoch to get the TotalSeconds. Then it converts that value to Int64() and finally to a string. I tried calling the methos ToLocalString but that's changing the date as well.
The date that I pass in is the date that I want to be converted to Int64 and eventually to a string. The datetime I pass in. Not changed.
I don't want to change the date that is passed in. I always pass in the date starting with 12:00:00AM (or 00:00:00) and that is the time I always want. Both of these methods change the date and or time. The date I pass in is 06/01/2017 12:00:00AM but sometimes it gets changed to 05/31/2017 04:00:00 or it keeps the date but the time is wrong. Dark Sky requires the date to be a value of Convert.ToInt64(milliseconds) and then converted to a string.
Does anybody know how to get the exact date and time that is passed in converted to Int64 using milliseconds?
I have the following Extensions class:
public static class Extensions
{
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static string ToLocalString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToLocalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
public static string ToUTCString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToUniversalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
}
This is the calling method:
public ForecastIORequest(string apiKey, float latF, float longF, DateTime time, Unit unit, Language? lang = null, Extend[] extend = null, Exclude[] exclude = null)
{
_apiKey = apiKey;
_latitude = latF.ToString(CultureInfo.InvariantCulture);
_longitude = longF.ToString(CultureInfo.InvariantCulture);
//_time = time.ToUTCString();
_time = time.ToLocalString();
//DateTime t = _time.
_unit = Enum.GetName(typeof(Unit), unit);
_extend = (extend != null) ? RequestHelpers.FormatExtendString(extend) : "";
_exclude = (exclude != null) ? RequestHelpers.FormatExcludeString(exclude) : "";
_lang = (lang != null) ? RequestHelpers.FormatLanguageEnum(lang) : Language.en.ToString();
}
There's a fundamental problem with the way you're handling dates here, and if I boil it down to one thing, I think the problem is that ToUniversalTime() doesn't work the way you think it does.
What ToUniversalTime() does is, simply giving the UTC time of a time that's defined in a different time zone. For example, say my local time is UTC-7. So if I define a DateTime object without specifying DateTimeKind and set the value to, say, 2017/6/1 9:00:00, that means, at that time the actual UTC time is 2017/6/1 16:00:00 at that time, and ToUniversalTime() will give you a DateTime object with that value.
Let me change your ToUTCString() method a little bit and show you the problem with it. It's returning a long value instead of string now, and I break down the first line of code into two.
public static long ToUTC(this DateTime _input)
{
var utcTime = _input.ToUniversalTime();
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
And notice that in your Extensions class, the UnixEpoch object's DateTimeKind is set to UTC. I changed the date to 2017/6/1 8:00:00 for the ease of understanding.
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
Now let's call that method with a DateTime object whose DateTimeKind is set to UTC.
// dateObj will have time 2017/6/1 9:00:00 _in UTC_.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
// This method converts to UTC, but it's already in UTC, so no actual conversion takes place.
// Then subtracts UnixEpoch from it, which is also in UTC.
long dateInLong = dateObj.ToUTC();
// The difference is one hour, so dateInLong will be 3600.
Console.WriteLine(dateInLong);
// This method adds the above difference to UnixEpoch, and displays the time.
Console.WriteLine(dateInLong.ToDateTime());
Now, here, everything is in UTC and you should see output as expected, like below:
3600
6/1/2017 09:00:00
All good so far.
Now change things a bit, and let's set our dateObj to local instead of UTC, as you do in your example.
// Notice that the object is in local time now.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
Now, the above dateObj will have time 9:00:00, but in my local time. My actual location is UTC-7 so note that this means 9AM local time for me is 4PM UTC. But note that we haven't changed the UnixEpoch object, which is still in UTC and time is set to 8AM UTC in it. And therefore, dateInLong will be 28,800 (8 hours x 60 mins x 60 seconds). So when your ToDateTime() method is called, it adds 28,000 seconds to 8AM UTC time, and returns as a DateTime object, of which time now is 4PM UTC.
28800
6/1/2017 16:00:00
And that's why depending on the time you set your dateObj to, your output changes time as you said.
Solution
You need to decide which time zone to use, and stick to that. One option would be to get rid of all the UTC conversions and have all times set in local time.
public static class Extensions
{
// NOT set to UTC
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static long ToUTC(this DateTime _input)
{
// NOT converted to UTC. So... change variable names accordingly.
var utcTime = _input;
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
}
class Program
{
static void Main(string[] args)
{
// Notice that the object is in local time and NOT UTC.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
Console.ReadLine();
}
}
The other option, set EVERYTHING to UTC, but then you'll have to make sure that the DateTime object on which you call ToUTC() is defined in UTC and not local.
So:
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
And
var utcTime = _input.ToUniversalTime();
And finally
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
BUT...
I see a bigger problem with you code, looking at the second code snippet. In the ForecastIORequest() constructor, you're saving time as a string. And that's not an ideal solution in my opinion. Because as you found the hard way, depending on what time zone the calling object was created, your time difference will be, well, different. And you'd have no way of knowing which.
I'd rather store the DateTime object as it is, and read it and calculate the difference when needed, taking into account time zones.
Hope this helps.
See DateTime.Ticks - there are 10,000 ticks in a millisecond. Simply take DateTime.Ticks / 10000 (ten thousand) and you have your milliseconds.
Here's a simple extension method to get the milliseconds as a long (that's Int64):
public static long ToMilliseconds(this DateTime dateTime)
{
return dateTime.Ticks / 10000;
}

Inconsistent DateTime to Unix Time conversion and error on 24 hour input

Attached is a method I am currently using that takes in a list of DateTime strings, their input format (i.e. yyyy-MM-dd HH:mm:ss), and their offset in the form of hours.
As for the culture and "standard", I am using InvariantCulture and I am converting the times to UTC.
public int unixFormat3(string dateTimeInput, string inputFormat, int hours)
{
DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
result = DateTime.ParseExact(dateTimeInput, inputFormat, provider);
int unixTime = (Int32)(result.ToUniversalTime().AddHours(hours).Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc))).TotalSeconds;
return unixTime;
}
Two issues with said method:
I am using this website as a comparison. If my input is 2014-03-18 21:00:00, my output, according to my method, is 1395190800, which converts back to 2014-03-19 01:00:00. It has a four hour difference. The desired output is this:
If my input is 2014-03-18 24:00:00, I get this error:
The DateTime represented by the string is not supported in calendar System.Globalization.GregorianCalendar.
Noticeably, it does not allow the input of 24 in the HH part. This is a weird error as NodaTime handles it just fine... Though that's irrelevant as I am using DateTime.
Does anyone have any insight on this area?
EDIT:
Upon some experimentation, removing the .ToUniversalTime() removes my 4-hour offset.. Why is this happening?
public int unixFormat3(string dateTimeInput, string inputFormat, int hours)
{
DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
result = DateTime.ParseExact(dateTimeInput, inputFormat, provider);
int unixTime = (Int32)(result.AddHours(hours).Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc))).TotalSeconds;
return unixTime;
}
This document, http://www.w3.org/TR/NOTE-datetime, cited in this question How to know whether a given string is a valid UTC DateTime format? does not list 24 as a valid hour value.
This document, http://en.wikipedia.org/wiki/Iso8601, cited by an answer to the question does list 24:00 as a valid time. This one, http://en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight, also says 24:00 is valid.
The System.DateTime object represents hours as an integer value between 0 and 23 (see http://msdn.microsoft.com/en-us/library/vstudio/system.datetime.hour(v=vs.100).aspx). As far as I know, NodaTime doesn't use any of the .NET provided DateTime or DateTimeOffset classes and handles everything itself, which is why it's handling an hour of 24 correctly.
As for why ToUniversalTime() is adding an offset, its probably because the ParseExact is returning a date that's already been adjusted. (What is the value of result just before you call ToUniversalTime()?)
You may also want to change your call to use this overload of ParseExact instead:
result = DateTime.ParseExact(dateTimeInput, inputFormat, provider, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
This tells the parser to assume the time is in UTC if no time zone is specified in the parsed string.
As a side note, you should probably declare your Unix epoch as a readonly global variable somewhere and use TryParseExact instead of ParseExact.
public class UnixTime
{
public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
public int unixFormat3(string dateTimeInput, string inputFormat, int hours)
{
int unixTime = -1;
DateTime result = DateTime.MinValue;
if (DateTime.TryParseExact(dateTimeInput, inputFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out result))
{
unixTime = (int)(result.AddHours(hours).Subtract(UnixTime.Epoch)).TotalSeconds;
}
return unixTime;
}
}

Converting the date within the places.sqlite file in Firefox to a DateTime

I am having some trouble converting a date found in the file that stores browser history to a normal DateTime.
The file is located at: C:\Users[username]\AppData\Roaming\Mozilla\Firefox\Profiles[profilename]\places.sqlite
The table in question is: [moz_places]
The column is: [last_visit_date]
I've tried using the unix epoch and webkit format(like chrome uses), but neither are giving me the results I expect.
Here is my Unix conversion(not working):
public static DateTime FromUnixTime(long unixTime)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
This is my webkit conversion code: (Also not working for these dates, it works with chromes webkit dates)
public static DateTime ConvertWebkitTimeToDateTime(long ticks)
{
//Set up a date at the traditional starting point for unix time.
DateTime normalDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
//Subtract the amount of seconds from 1601 to 1970.
long convertedTime = (ticks - 11644473600000000);
//Devide by 1000000 to convert the remaining time to seconds.
convertedTime = convertedTime / 1000000;
//Add the seconds we calculated above.
normalDate = normalDate.AddSeconds(convertedTime);
//Finally we have the date.
return normalDate;
}
So what's the deal with these dates Firefox is storing? Here are a couple sample dates that should all be around today's date or yesterday's.(about 10/17/2013)
1373306583389000
1373306587125000
1373306700392000
Any help or documentation links would be awesome, thanks.
Unix timestamps are measured in seconds.
These values are larger by a factor of one million, i.e., they are using microseconds:
> select datetime(1373306583389000 / 1000000, 'unixepoch');
2013-07-08 18:03:03
Solution in C#:
public static DateTime FromUnixTime(long unixTime)
{
unixTime = unixTime / 1000000;
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
CL. was correct in that this is simply the millisecond value from the Unix epoch.
Solution in SQL:
Here is a resource that explains his solution in greater detail:
https://support.mozilla.org/en-US/questions/835204

Convert LDAP AccountExpires to DateTime in C#

I want to convert 18 digit string from LDAP AccountExpires to Normal Date Time Format.
129508380000000000 >> May 26 2011
I got the above conversion from using the following link.
http://www.chrisnowell.com/information_security_tools/date_converter/Windows_active_directory_date_converter.asp?pwdLastSet,%20accountExpires,%20lastLogonTimestamp,%20lastLogon,%20and%20badPasswordTime
I tried to convert by using DateTime.Parse or Convert.ToDateTime. But no success.
Anyone know how to convert it? Thanks very much.
Edited answer
It's the number of ticks since Jan-01-1601 in UTC, according to Reference, which describes the significance of the year 1601. Good background reading.
var accountExpires = 129508380000000000;
var dt = new DateTime(1601, 01, 01, 0, 0, 0, DateTimeKind.Utc).AddTicks(accountExpires);
Original Accepted Answer
It's the number of ticks since Jan-02-1601.
DateTime dt = new DateTime(1601, 01, 02).AddTicks(129508380000000000);
You can use the FromFileTime method on the DateTime class, but watch out, when this field is set to not expire, it comes back as the Int64.MaxValue and doesn't work with either of these methods.
Int64 accountExpires = 129508380000000000;
DateTime expireDate = DateTime.MaxValue;
if (!accountExpires.Equals(Int64.MaxValue))
expireDate = DateTime.FromFileTime(accountExpires);
Some info for anyone who came here looking to set the AccountExpires value.
To clear the expiry is nice and easy:
entry.Properties["accountExpires"].Value = 0;
However if you try to directly write back an int64 / long:
entry.Properties["accountExpires"].Value = dt.ToFileTime();
You can get a 'COMException was unhandled - Unspecified error'
Instead write back the value as a string data type:
entry.Properties["accountExpires"].Value = dt.ToFileTime().ToString();
Be aware of the time of day you are setting, for consistancy with ADUC the time should be 00:00.
Instead of .Now or .UtcNow you can use .Today:
var dt1 = DateTime.Today.AddDays(90);
entry.Properties["accountExpires"].Value = dt1.ToFileTime().ToString();
Other input like dateTimePicker you can replace the time, Kind as Local for the Domain Controller:
var dt1 = dateTimePicker1.Value;
var dt2 = new DateTime(dt1.Year, dt1.Month, dt1.Day, 0, 0, 0, DateTimeKind.Local);
entry.Properties["accountExpires"].Value = dt2.ToFileTime().ToString();
If you View Source on the link you posted you should see a Javascript conversion algorithm that should translate quite nicely to c#
For Ruby
def ldapTimeConverter(ldap_time)
Time.at((ldap_time/10000000)-11644473600)
end
I stumbled across this working on a PowerShell script. I found I can query the accountexpirationdate property and no conversion is required.
Someone had the "best" way above but when it's set to never expired, the value is zero.
public static DateTime GetAccountExpiresDate(DirectoryEntry de)
{
long expires = de.properties["accountExpires"].Value;
if (expires == 0) // doesn't expire
return DateTime.MaxValue;
return DateTime.FromFileTime(expires);
}
I'll provide a perfect answer to this question using which you will be able to convert and DateTime to active directory long int format and will be also able to do the vice versa of it.
Here is a solution to it:-
To get DateTime from AD
string tickstring = de.Properties["accountExpires"][0].ToString();
long Ticks = (long) tickstring;
DateTime ReferenceDate = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long ExpireDateTicks = Ticks + ReferenceDate.Ticks;
DateTime ExpireDate = new DateTime(ExpireDateTicks);
To convert DateTime to AD long integer format
DateTime ReferenceDate = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime ExpireDate = new DateTime(Request.EndDate.Year, Request.EndDate.Month, Request.EndDate.Day, 0, 0, 0);
long Ticks = ExpireDate.Ticks - ReferenceDate.Ticks;
NewUser.accountExpires = Ticks.ToString();

Categories

Resources