I have an Android App and a C# mvc Web API. I want to sent a Date (and some other data) with a HttpPOST from the Android App to the WebAPI.
Right now I use long ticks = myDate.getTime(); in Android and DateTime date = new DateTime(ticks); in C#.
With the Date 2014-06-11 00:00:00 my ticks in Android is 1402459200000 and my DateTime in C# is 0001-01-02T14:57:25 PM
How to properly convert a Date to long and from long to DateTime, from Android to C#?
PS: I could send a String date in Android, then convert it to a DateTime date and convert that to long ticks in C#, but since I need a long C# for a method I can't change the parameters of, I would prefer to just send the correct long from Android directly.
Date in Java doesn't have ticks - it has milliseconds. Additionally, the epoch for Date is the Unix epoch (1970-01-01) whereas the epoch for DateTime is 0001-01-01. You need to take both of these into account - as well as the fact that the epoch of Date is in UTC, whereas the epoch of DateTime varies depending on kind. You probably want something like:
private static readonly UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0,
DateTimeKind.Utc);
...
long millis = ...;
DateTime dateFromJavaApp = UnixEpoch + Timespan.FromMilliseconds(millis);
Or you could use my Noda Time library which makes this (and many other things) simpler:
long millis = ...;
Instant instant = Instant.FromMillisecondsSinceUnixEpoch(millis);
Take a look at DateTimeOffset.FromUnixTimeMilliseconds().
Related
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");
I have date time in a string as "20160127003500".
What I need to do is convert this to Unix time-stamp adding hours to it.
I want to add hours offset as "1" or "2" or "24".
Can anyone please guide me in right direction.
Regards
First, parse the entire string (including the offset you mentioned in the question comments) to a DateTimeOffset:
using System.Globalization;
string s = "20160129205500 +0100";
string format = "yyyyMMddHHmmss zzz";
DateTimeOffset dto = DateTimeOffset.ParseExact(s, format, CultureInfo.InvariantCulture);
Then, there are a few different ways to get a Unix timestamp. Note that by the pure definition of a "Unix timestamp", the result would be in terms of seconds, though many languages these days use a higher precision (such as milliseconds used in JavaScript).
If you are targeting .NET 4.6 or higher, simply use the built-in methods:
// pick one for the desired precision:
long timestamp = dto.ToUnixTimeMilliseconds();
long timestamp = dto.ToUnixTimeSeconds();
If you are targeting an earlier version of .NET, then compute it yourself:
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
// pick one for the desired precision:
long timestamp = (long) dto.UtcDateTime.Subtract(epoch).TotalMilliseconds;
long timestamp = (long) dto.UtcDateTime.Subtract(epoch).TotalSeconds;
I cannot for the life of me deserialize a date string which I am told is ISO 8601 (e.g. '1396949418557') to a C# DateTime object.
I really like what I've read about Noda Time, and I am using JSON.NET. Has anyone come across this?
Using Noda Time:
Instant instant = Instant.FromMillisecondsSinceUnixEpoch(1396949418557);
It looks like a unix timestamp. Try this:
var unixEraStart = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var dateTime = unixEraStart.AddMilliseconds(1396949418557);
Your string looks like a Javascript timestamp (milliseconds since 1970/01/01, effectively 1000 * unix time).
I've never used nodatime, but it looks like that library defines time in terms of ticks since the unix epoch, with 10,000 ticks = 1 millisecond. So if you do an Int64.Parse of your string, then multiply it by 10,000, you should be able to construct a nodatime date object with that value.
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);
I'm working with pbx for voip calls. One aspect of pbx is that you can choose to receive CDR packages. Those packages have 2 timestamps : "utc" and "local", but both seem to always be the same.
Here's an example of a timestamp : "1268927156".
At first sight, there seems to be no logic in it. So I tried converting it several ways, but with no good result. That value should provide a time around 11am (+1GMT) today.
Things I tried:
Datetime dt = new Datetime(number);
Timespan ts = new Timespan(number);
DateTime utc = new DateTime(number + 504911232000000000, DateTimeKind.Utc)
and some others I can't remember right now.
Am I missing something stupid here?
Thanks in advance
This looks like Unix time.
1268927156 = Thu, 18 Mar 2010 15:45:56 GMT
And a code sample:
DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
DateTime time = startDate.AddSeconds(1268927156 );
Seems to be a Unix timestamp (no. of seconds since the epoch)
DateTime translated = new DateTime(1970,1,1).AddSeconds(1268927156);
should give you the date and time you were after...
That looks like a unix timestamp, which is the no. of seconds since Jan 01,1970.
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(1268927156);
If both the utc and local timestamps are the same, the timezone on your PBX is either set to UTC, and your timestamps really are UTC, or the timezone is set to UTC but the time is set to your local time, and you get your local time for both of the timestamps. You'll have to figure out which of those so you'll know wether to convert the timestamps from UTC or not.
I guess this is a UNIX timestamp, the logic would be the following:
The UNIX timestamp represents the time measured in number of seconds since the Unix Epoch (1st of January 1970 00:00:00 GMT)
There is a codeproject article explaining the conversion. Basically what you need to do would be the following:
// First make a System.DateTime equivalent to the UNIX Epoch.
System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
// Add the number of seconds in UNIX timestamp to be converted.
dateTime = dateTime.AddSeconds(timestamp);