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);
Related
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;
We have DateTimeOffsets in Database/Model. To display these values in Web, we convert the DateTimeOffsets into the current user's timezone.
According MSDN, DateTimeOffset can be ambiguous in a specific TimeZone:
TimeZoneInfo.IsAmbiguousTime Method (DateTimeOffset)
This doesn't make sense to me at all. Can someone please give me an example DateTimeOffset which is ambiguous?
We're in TimeZone "W. Europe Standard Time".
Does what the documentation says not make it clear?
Typically, ambiguous times result when the clock is set to return to standard time from daylight saving time
I.e. if at 2am you come off of DST and reset the clock to 1am, then if someone starts talking about 1.30am, you don't know if that's 30 minutes from now or happened 30 minutes in the past.
There are a set of values (typically an hour long) which map to two different set of moments in UTC time.
I think the confusion comes from the way that "ambiguous" is defined here.
To be clear, a DateTimeOffset is never ambiguous unto itself. It always represents a specific moment in absolute, instantaneous time. Given a date, time, and offset, I can tell you both the local wall-time, and the precise UTC time (by applying the offset).
However, the wall-time portion of the value can be ambiguous within a specific time zone. That is, the date and time only when you ignore the offset. That's what TimeZoneInfo.IsAmbiguousTime is telling you. That if it weren't for the offset, the value would be ambiguous. The wall-time may be one that a person in that time zone might find confusing.
Consider that there are two overloads of this method, one that takes a DateTime and one that takes a DateTimeOffset.
The DateTime one makes perfect sense when .Kind is DateTimeKind.Unspecified.
DateTime dt = new DateTime(2016, 10, 30, 2, 0, 0);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dt); // true
It makes a little less sense with the other kinds, because it does conversions to the given time zone first - but still it does the same thing:
DateTime dt = new DateTime(2016, 10, 30, 1, 0, 0, DateTimeKind.Utc);
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dt); // true
The DateTimeOffset overload is essentially doing the same thing as the previous example. Whatever the offset is, it gets applied to the date and time, then ambiguity is checked on the resulting date and time alone - just like in the first example.
DateTimeOffset dto = new DateTimeOffset(2016, 10, 30, 2, 0, 0, TimeSpan.FromHours(1));
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dto); // true
Even with an offset that is meaningless to that time zone, it still gets applied before comparing.
DateTimeOffset dto = new DateTimeOffset(2016, 10, 29, 19, 0, 0, TimeSpan.FromHours(-5));
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool ambiguous = tz.IsAmbiguousTime(dto); // true
It boils down to the implementation of the overload, which is essentially:
// Make sure the dto is adjusted to the tz. This could be a no-op if it already is.
DateTimeOffset adjusted = TimeZoneInfo.ConvertTime(dto, tz);
// Then just get the wall time, stripping away the offset.
// The resulting datetime has unspecified kind.
DateTime dt = adjusted.DateTime;
// Finally, call the datetime version of the function
bool ambiguous = tz.IsAmbiguousTime(dt);
You can see this in the .net reference source here. They condense it to two lines, and preface it with a shortcut for better perf when DST is not applicable, but that's what it does.
Well the sample is (the last October's Sunday 2:00-3:00)
DateTimeOffset example = new DateTimeOffset(2015, 10, 25, 2, 30, 0,
new TimeSpan(0, 2, 0, 0));
TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
if (tst.IsAmbiguousTime(example))
Console.Write("Ambiguous time");
Opposite to Ambiguous time is Invalid time (the last March's Sunday 2:00-3:00):
TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
if (tst.IsInvalidTime(new DateTime(2016, 03, 27, 2, 30, 0)))
Console.Write("Invalid time");
I have a datetime object, and I know the UTC offset (double). How can I get UTC time from these two pieces of information?
All of the examples I've seen require a timezone. Well, I don't know what timezone is, and it shouldn't really matter. If i have an offset of -7, it could either be PDT, or it could be MST - it's really irrelevant as either would produce the same UTC. It seems really stupid that I have to convert the offset that I have to a timezone just so the "ToUniversalTime" can pull the offset back out.
Honestly, I'm about to resort to just using something like this:
DateTime dateTime = new DateTime(2014, 8, 6, 12, 0, 0);
Double timeZone = -7.0;
string utc = String.Format("{0}-{1}-{2}T{3}:{4}:{5}{6}:{7}", startDate.Year, startDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second, (int) Math.Floor(timeZone), (timeZone % 1) * 60);
can someone please tell me why this is a bad idea?
(someone will probably close this as a duplicate, but I looked at a dozen other questions and none of them were quite the same - they all used the TimeZoneInfo object).
Just use DateTimeOffset:
TimeSpan utcOffset = TimeSpan.FromHours(timeZone);
DateTimeOffset result = new DateTimeOffset(dateTime, utcOffset);
DateTime utc = result.UtcDateTime;
or
string utc = result.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
It's not clear why you want it as a string in the end though...
(You might also want to consider using my Noda Time project, particularly as you're likely to see time zone IDs which are TZDB time zones...)
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().
In C#, how can I get the current DateTime in the following format? 2011-08-10T21:36:01.6327538Z
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")
Note that if you're not using DateTime.UtcNow and are instead using an existing DateTime instance, you may need to convert it to universal time before using the given format string (e.g. DateTime.ToUniversalTime())
Keep in mind that DateTime.Now is sometimes only precise to a thousandth of a second, depending on the system clock. This page shows the following:
It is possible to display very small fractional units of a second, such as ten thousandths of a second or hundred-thousandths of a second. However, these values may not be meaningful. The precision of date and time values depends on the resolution of the system clock. On Windows NT 3.5 and later, and Windows Vista operating systems, the clock's resolution is approximately 10-15 milliseconds.
However, if you populate the DateTime yourself, you can make it more precise. I am not aware of any other built-in libraries that are more precise than DateTime.UtcNow.
Also, DateTime.UtcNow.ToString("o") will give you an ordinal datetime string. This doesn't always specify the timezone at the end, so you'd still need to add Z to the end if you knew were dealing with Utc and the DateTime format was Unspecified
If you want your times in UTC (which is what the Z implies) then you need to ensure that they are UTC times...
i.e.
DateTime.UtcNow.ToString("O");
or assuming that you know that your datetime is local...
DateTime foo = MethodThatReturnsALocalTime();
foo.ToUniversalTime().ToString("O");
FWIW: DateTime.UtcNow is faster than DateTime.Now because it doesn't need to do a timezone lookup, on Compact Framework that difference can be very noticeable for some reason.
You can try either:
DateTime.Now.ToString("o");
which also includes the timezone component. - OR -
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffffff")
Try this:
var xs = DateIime.Now;
var frmtdDatetime = xs.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffff");
and check out this msdn link
You want a date in ISO 8601 format.
Use the "O" round-trip format with a date in UTC:
// 2022-12-22T10:20:30.4567890Z
string formatted = DateTime.UtcNow.ToString("O");
If your DateTime is not marked as UTC, the round-trip format is still round-trip but the date won't have the Z at the end:
// 2022-12-22T10:20:30.4567890Z+09:00
string local = DateTime.Now.ToString("O");
// 2022-12-22T10:20:30.4567890Z
string unspecified = new DateTime(2022, 12, 24, 0, 0, 0, DateTimeKind.Unspecified).ToString("O");
We see that local times add a time offset instead of a Z, and Unspecified times cannot add any information on time offset.
This is where problems start. Don't just add a Z at the end!
Pitfall
But why can't we just add a Z at the end?
Because 10h:20m:30s local is not the same as 10h:20m:30s UTC.
Let's assume we are in Japan.
If a date is local, 11:00:00AM is actually 02:00:00Z and not 11:00:00Z.
Let's see how bad data can interfere:
long ticks = 638074368000000000L;
var utc = new DateTime(ticks, DateTimeKind.Utc);
var local = new DateTime(ticks, DateTimeKind.Local);
var unspecified = new DateTime(ticks, DateTimeKind.Unspecified);
var utcAsLocal = utc.ToLocalTime();
var localAsUtc = new DateTime(ticks, DateTimeKind.Local);
var localFromLocalClock = new DateTime(2022, 12, 24, 9, 0, 0, DateTimeKind.Local);
var utcFromLocalClock = localFromLocalClock.ToUniversalTime();
Console.WriteLine($"UTC: {utc:O}"); // 1 OK: 2022-12-24T00:00:00.0000000Z
Console.WriteLine($"Local: {local:O}"); // 2 ??: 2022-12-24T00:00:00.0000000+09:00
Console.WriteLine($"Unspecified: {unspecified:O}"); // 3 OK: 2022-12-24T00:00:00.0000000
Console.WriteLine($"UTC>Local: {utcAsLocal:O}"); // 4 OK: 2022-12-24T09:00:00.0000000+09:00
Console.WriteLine($"Local>Utc: {localAsUtc:O}"); // 5 ??: 2022-12-24T00:00:00.0000000+09:00
Console.WriteLine($"!Local: {localFromLocalClock:O}"); // 6 OK: 2022-12-24T09:00:00.0000000+09:00
Console.WriteLine($"!UTC: {utcFromLocalClock:O}"); // 7 OK: 2022-12-24T00:00:00.0000000Z
Notice that the local date does not represent the same universal instant as the UTC and Unspecified datetimes! Lines 2 and 5 are actually different instants.
The localFromLocalClock does.
So if we get a date that is not in UTC and just format it either without timezone or adding a Z, we're corrupting the data.
We often become vulnerable to bugs due to this. We should be careful when manipulating dates.
This is why your UTC requirement for the date is important.
Suggested reading
The Noda Time API was built (by Jon Skeet!) to deal with this.
It presents a good set of data structures that ensure that we work with dates correctly.