GroupWise 2014 Date Format to DateTime - c#

I'm working with the GroupWise 2014 Rest API and I have a problem parsing their date format.
When you fetch a user you receive a json object with "timeCreated": 1419951016000,
But I can't figure out what format that date is.
I've tried
DateTime.Parse
DateTime.FromFileTime
DateTime.FromFileTimeUtc
The value 1419951016000 should be around the time 2014-12-30 15:50

Looks like unix time in milliseconds since January 1st, 1970 at UTC. Current unix time in seconds is shown here as 1419964283.
To convert to a DateTime to unix time, see here: How to convert UNIX timestamp to DateTime and vice versa?. That code works for unix time in seconds; the following works for unix time in milliseconds, represented as a long:
public static class UnixTimeHelper
{
const long MillisecondsToTicks = 10000;
static readonly DateTime utcEpochStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
static DateTime UtcEpochStart { get { return utcEpochStart; }}
public static DateTime ToDateTime(long unixTimeInMs, DateTimeKind kind)
{
var dateTime = UtcEpochStart + new TimeSpan(MillisecondsToTicks * unixTimeInMs);
if (kind == DateTimeKind.Local)
dateTime = dateTime.ToLocalTime();
return dateTime;
}
public static long ToUnixTimeInMs(DateTime dateTime)
{
if (dateTime.Kind == DateTimeKind.Local)
dateTime = dateTime.ToUniversalTime();
var span = dateTime - UtcEpochStart;
return (long)(span.Ticks / MillisecondsToTicks);
}
}
With this code. UnixTimeHelper.ToDateTime(1419951016000, DateTimeKind.Utc).ToString() gives the value "12/30/2014 2:50:16 PM". Is your desired value of "2014-12-30 15:50" in UTC or your local time?
If you are using Json.NET to serialize your JSON, you can write a custom JsonConverter to do the conversion automatically from a DateTime property using the instructions here: Writing a custom Json.NET DateTime Converter . That code also works for unix time in seconds and so will need to be tweaked.
(Finally, seconding Plutonix's suggestion to double-check the documentation. In particular you need to read what the documentation says about the time zone in which the times are returned. It's probably UTC but it pays to make sure.)
Update
After a quick search the online doc looks pretty bad, but this page makes mention of
expiretime
long
Optional. Use an explicit expiration cut-off time. The time is specified as a java long time.
java.util.Date represents "the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT" as a long.

Related

How to set timezone based timestamp to get current date and time in C#? [duplicate]

This code has been working for a long time now but has broken now when I try to pass DateTime.Now as the outageEndDate parameter:
public Outage(DateTime outageStartDate, DateTime outageEndDate, Dictionary<string, string> weeklyHours, string province, string localProvince)
{
this.outageStartDate = outageStartDate;
this.outageEndDate = outageEndDate;
this.weeklyHours = weeklyHours;
this.province = province;
localTime = TimeZoneInfo.FindSystemTimeZoneById(timeZones[localProvince]);
if (outageStartDate < outageEndDate)
{
TimeZoneInfo remoteTime = TimeZoneInfo.FindSystemTimeZoneById(timeZones[province]);
outageStartDate = TimeZoneInfo.ConvertTime(outageStartDate, localTime, remoteTime);
outageEndDate = TimeZoneInfo.ConvertTime(outageEndDate, localTime, remoteTime);
The error message I am getting on the last line is that the Kind property is not set correctly on the DateTime parameter (outageEndDate). I've Googled and checked SO for examples but I don't really understand the error message.
Any advice is appreciated.
Regards.
EDIT - The exact error message is:
The conversion could not be completed because the supplied DateTime did not have the Kind
property set correctly. For example, when the Kind property is DateTimeKind.Local, the source
time zone must be TimeZoneInfo.Local. Parameter name: sourceTimeZone
EDIT: outageEndDate.Kind = Utc
Thanks for clarifying your question.
If the DateTime instance Kind is Local, then TimeZoneInfo.ConvertTime will expect the second parameter to be the local timezone of your computer.
If DateTime instance Kind is Utc, then TimeZoneInfo.ConvertTime will expect the second parameter to be the Utc timezone.
You need to convert outageEndDate to the right timezone first, just in case the localProvice timezone doesn't match the timezone on your computer.
outageEndDate = TimeZoneInfo.ConvertTime(outageEndDate, localTime);
here is an example of something that you could try
It depends on what you mean by "a GMT + 1 timezone". Do you mean permanently UTC+1, or do you mean UTC+1 or UTC+2 depending on DST?
If you're using .NET 3.5, use TimeZoneInfo to get an appropriate time zone, then use:
// Store this statically somewhere
TimeZoneInfo maltaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("...");
DateTime utc = DateTime.UtcNow;
DateTime malta = TimeZoneInfo.ConvertTimeFromUtc(utc, maltaTimeZone );
You'll need to work out the system ID for the Malta time zone, but you can do that easily by running this code locally:
Console.WriteLine(TimeZoneInfo.Local.Id);
If you're not using .NET 3.5, you'll need to work out the daylight savings yourself. To be honest, the easiest way to do that is going to be a simple lookup table. Work out the DST changes for the next few years, then write a simple method to return the offset at a particular UTC time with that list hardcoded. You might just want a sorted List<DateTime> with the known changes in, and alternate between 1 and 2 hours until your date is after the last change:
// Be very careful when building this list, and make sure they're UTC times!
private static readonly IEnumerable<DateTime> DstChanges = ...;
static DateTime ConvertToLocalTime(DateTime utc)
{
int hours = 1; // Or 2, depending on the first entry in your list
foreach (DateTime dstChange in DstChanges)
{
if (utc < dstChange)
{
return DateTime.SpecifyKind(utc.AddHours(hours), DateTimeKind.Local);
}
hours = 3 - hours; // Alternate between 1 and 2
}
throw new ArgumentOutOfRangeException("I don't have enough DST data!");
}

Adding Seconds to DateTime with a Valid Double Results in ArgumentOutOfRangeException

The following code crashes and burns and I don't understand why:
DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
double d = double.Parse("1332958778172");
Console.Write(dt.AddSeconds(d));
Can someone tell me what's going on? I just can't seem to be able to figure out why...
EDIT
This value comes back from the Salesforce REST API and from what I understand it's a Unix epoch time stamp. "The time of token issue, represented as the number of seconds since the Unix epoch (00:00:00 UTC on 1 January 1970)."
SOLUTION
Salesforce REST API is in fact sending milliseconds back for the issued_at field when performing the OAuth request when they say they're sending seconds...
As others have said, the problem is that the value is too large.
Having looked over it, I believe it represents milliseconds since the Unix epoch, not seconds so you want:
DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
double d = double.Parse("1332958778172"); // Or avoid parsing if possible :)
Console.Write(dt.AddMilliseconds(d));
Either that, or divide by 1000 before calling AddSeconds - but obviously that will lose data.
The value you are adding results in a date outside of the valid range of dates that a DateTime supports.
DateTime supports 01/01/0001 00:00:00 to 31/12/9999 23:59:59.
A simple calculation of 1332958778172/3600/24/365 gives 42267 years.
I think the double value is genuinely too large. It represents just over 42,267 years (if my maths is correct), and DateTime.MaxValue is 23:59:59.9999999, December 31, 9999
DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
Console.Write(dt.AddSeconds(1332958778172D));
Except that...
1332958778172/60/60/24/365 = 42,267 years... which DateTime can only go up to 23:59:59.9999999, December 31, 9999
I had a similar issue where I was required to add a configurable timespan to a datetime.
If the configuration is not correct I have to assume the 'worst scenario' : MaxValue.
I solved it by implementing an extension to DateTime (still in test phase) :
/// <summary>
/// Removes a timespan from a date, returning MinValue or MaxValue instead of throwing exception when if the resulting date
/// is behind the Min/Max values
/// </summary>
/// <returns></returns>
public static DateTime SafeAdd(this DateTime source, TimeSpan value)
{
// Add or remove ?
if (value.Ticks > 0)
{
// add
var maxTicksToAdd = DateTime.MaxValue - source;
if (value.Ticks > maxTicksToAdd.Ticks)
return DateTime.MaxValue;
}
else
{
var maxTicksToRemove = source - DateTime.MinValue;
// get the value to remove in unsigned representation.
// negating MinValues is impossible because it would result in a value bigger than MaxValue : (-32768 .. 0 .. 32767)
var absValue = value == TimeSpan.MinValue ? TimeSpan.MaxValue : -value;
if (absValue.Ticks > maxTicksToRemove.Ticks)
return DateTime.MinValue;
}
return source + value;
}
Looks like this timestamp is in milliseconds, try below code it should work fine.
DateTime nDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
double epoch = 1585008000000;
DateTime rDate = nDateTime.AddMilliseconds(epoch);
In my case I had to consume an api object as a double and convert the unix time to a DateTime:
DateTime Date = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Double.Parse("1596225600000"));

How to convert javascript numeric date into C# date (using C#, not javascript!)

I'm scraping a website and in the html it has a date in the following format:
"date":"\/Date(1184050800000-0700)\/"
If this was in javascript, it would be a date object and I could use its methods to retrieve the data in whatever format I like. However, I'm scraping it in a C# app. Does anyone know what this format is? Is it the total number of seconds after a certain date or something? I need a way to convert this to a C# datetime object.
If I'm not mistaken, that is a Unix timestamp in milliseconds. 1184050800000 is the timestamp itself, and -0700 is the time zone. This epoch convertor confirms.
Here is some code I've used before for converting Unix timestamps into DateTimes. Be sure to include only the part before -0700:
/// <summary>
/// Converts a Unix timestamp into a System.DateTime
/// </summary>
/// <param name="timestamp">The Unix timestamp in milliseconds to convert, as a double</param>
/// <returns>DateTime obtained through conversion</returns>
public static DateTime ConvertFromUnixTimestamp(double timestamp)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp / 1000); // convert from milliseconds to seconds
}
If you encounter Unix timestamps that are in seconds, you just have to remove the / 1000 part of the last line of the code.
As sinelaw says it seems to be a regex of some sort, however I tried parsing out the numeric values:
1184050800000-0700
And they seem to correspond to:
1184050800000 - Unix timestamp in milliseconds
-0700 - this would be the timezone offset UTC-07:00
You could parse it (I assume it's a string from a JSON object) and convert it to a DateTime like this:
string dateString = "/Date(1184050800000-0700)/";
Regex re = new Regex(#"(\d+)([-+]\d{4})");
Match match = re.Match(dateString);
long timestamp = Convert.ToInt64(match.Groups[1].Value);
int offset = Convert.ToInt32(match.Groups[2].Value) / 100;
DateTime date = new DateTime(1970, 1, 1).AddMilliseconds(timestamp).AddHours(-offset);
Console.WriteLine(date); // 7/10/2007 2:00:00 PM
Am I wrong? It looks like a regexp to me, not a date object at all.
DateTime now = new DateTime(1184050800000);
Console.WriteLine(now); // 2/01/0001 8:53:25 AM
Could this be correct if you aren't interested in the year?

How to represent the current UK time?

I'm facing an issue while converting dates between my server and client where both is running in Germany. The Regional settings on the client machines could be set to both UK or Germany.I recieve a date from the server which is CET format, and I need to represent this time on UI as UK time. For example a time recieved from server like say, 01/07/2010 01:00:00 should be represented on the UI as 01/07/2010 00:00:00. I have written a converter for this purpose, however while running it 'am getting a time difference of 2 hours.Below is the code, please can you help?
public class LocalToGmtConverter : IDateConverter
{
private readonly TimeZoneInfo timeZoneInfo;
public LocalToGmtConverter()
: this(TimeZoneInfo.Local)
{
}
public LocalToGmtConverter(TimeZoneInfo timeZoneInfo)
{
this.timeZoneInfo = timeZoneInfo;
}
public DateTime Convert(DateTime localDate)
{
var utcKind = DateTime.SpecifyKind(localDate, DateTimeKind.Utc);
return utcKind;
}
public DateTime ConvertBack(object fromServer)
{
DateTime serverDate = (DateTime)fromServer;
var utcOffset = timeZoneInfo.GetUtcOffset(serverDate);
var uiTime = serverDate- utcOffset;
return uiTime;
}
}
I think you're converting to UTC (instead of UK) time. Since there is still summer time in Central Europe (event if the temperatures say otherwise), the difference is +2 hours until October, 31st.
If you know that you're converting from Germany to UK (i.e. CEST to BST in summer and CET to GMT in winter), why you don't just subtract 1 hour?
If you want the time zone information for UK, you can construct it using
var britishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Then you could convert the date using
var newDate = TimeZoneInfo.ConvertTime(serverDate, TimeZoneInfo.Local, britishZone);
This is what I do:
var BritishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime dt = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified);
DateTime DateTimeInBritishLocal = TimeZoneInfo.ConvertTime(dt, TimeZoneInfo.Utc, BritishZone);
I needed to add the SpecifyKind part or the ConvertTime throws an exception
Use TimeZoneInfo.ConvertTime to convert original input timezone (CET) to target timezone (UK).
public static DateTime ConvertTime(
DateTime dateTime,
TimeZoneInfo sourceTimeZone,
TimeZoneInfo destinationTimeZone
)
Full guidance on MSDN here:
Converting Times Between Time Zones
Modified code sample from MSDN:
DateTime ceTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
TimeZoneInfo ceZone = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
Console.WriteLine("{0} {1} is {2} GMT time.",
ceTime,
ceZone.IsDaylightSavingTime(ceTime) ? ceZone.DaylightName : ceZone.StandardName,
TimeZoneInfo.ConvertTime(ceTime, ceZone, gmtZone));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("The registry does not define the required timezones.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the required timezones has been corrupted.");
}
The better approach to deal with local times is store them in unified representation such as UTC.
So you can convert all input times to UTC (via .ToUniversalTime()), and store (or transmit) its value. When you need to show it just convert back by using .ToLocalTime().
So you avoid rquirements to know which time zone was original value and can easily show stored value in different timezones.
Also you can avoid incoming troubles where you have to write specific logic for processing time in next timezone trying to figure out how to convert them amongs all available.
I realize the question is for C#, but if all you want to do is a single conversion you can do this from the PowerShell command line:
$d = [DateTime]::Parse("04/02/2014 17:00:00")
$gmt = [TimeZoneInfo]::FindSystemTimeZoneById("GMT Standard Time");
[TimeZoneInfo]::ConvertTime($d, $gmt, [TimeZoneInfo]::Local)
This script would convert 17:00 UK time into your local time zone.
For me, that would be CST. It's interesting to note that if I had set the date to 03/27/2014, the result would be different because the UK daylight saving time kicks in on different dates that the US.

Convert C# DateTime object to libpcap capture file timestamp

I am stuck in converting a DateTime object to a timestamp for the libpcap capture file format (is also used by wireshark, file format definitiom) in C#. The timestamp I can't manage to convert my object to is the Timestamp in the packet (record) header (guint32 ts_sec and guint32 ts_usec).
You can do it like so:
DateTime dateToConvert = DateTime.Now;
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan diff = date - origin;
// Seconds since 1970
uint ts_sec = Math.Floor(diff.TotalSeconds);
// Microsecond offset
uint ts_usec = 1000000 * (diff.TotalSeconds - ts_sec);
It is best to convert the Unix Epoch and your dateToConvert to UTC before any manipulation. There is a constructor for DateTime that takes a DateTimeKind for constructing the UnixEpoch, and there is a ToUniversalTime() method for the dateToConvert. If you always want Now, there is a handy DateTime.UtcNow property that takes care of that for you. The code as written shouldn't have any problems, but if you make this a function, a UTC date could be passed and working with a UTC target date and a local Unix Epoch would certainly not give the right results unless you are in GMT and not on summer time.

Categories