I need to convert UTC date strings to DateTimeOffsets.
This must work with a timezone which differs from the computers timezone.
E.g. current computer timezone is +02:00, but I want to create a DateTimeOffset with offset -4:00.
I already read lot of questions here on stackoverflow, but none of them solved my problem.
That is what I need to do:
Input: "2012-11-20T00:00:00Z"
Output: DateTimeOffset with:
UtcDateTime of 2012-11-20 00:00
the correct Utc offset for the defined timezone (01:00 in this example)
LocalDateTime: 2012-11-20 01:00 (= UtcDateTime + Offset)
Of course daylight saving must be taken into account.
edit:
To make things even clearer, please try to complete the following code snippet:
DateTimeOffset result;
const string dateString = "2012-11-20T00:00:00Z";
var timezone = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); //this timezone has an offset of +01:00:00 on this date
//do conversion here
Assert.AreEqual(result.Offset, new TimeSpan(1, 0, 0)); //the correct utc offset, in this case +01:00:00
Assert.AreEqual(result.UtcDateTime, new DateTime(2012, 11, 20, 0, 0, 0)); //equals the original date
Assert.AreEqual(result.LocalDateTime, new DateTime(2012, 11, 20, 1, 0, 0));
Here is the solution you are looking for:
const string dateString = "2012-11-20T00:00:00Z";
TimeZoneInfo timezone = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); //this timezone has an offset of +01:00:00 on this date
DateTimeOffset utc = DateTimeOffset.Parse(dateString);
DateTimeOffset result = TimeZoneInfo.ConvertTime(utc, timezone);
Assert.AreEqual(result.Offset, new TimeSpan(1, 0, 0)); //the correct utc offset, in this case +01:00:00
Assert.AreEqual(result.UtcDateTime, new DateTime(2012, 11, 20, 0, 0, 0)); //equals the original date
Assert.AreEqual(result.DateTime, new DateTime(2012, 11, 20, 1, 0, 0));
Note that you were incorrectly testing the .LocalDateTime property - which is always going to convert the result to the local time zone of the computer. You simply need the .DateTime property instead.
Is this what you want:
[Test]
public void ParseUtcDateTimeTest()
{
DateTime dateTime = DateTime.Parse("2012-11-20T00:00:00Z");
Assert.AreEqual(new DateTime(2012, 11, 20, 01, 00, 00), dateTime);
DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime);
Assert.AreEqual(new TimeSpan(0, 1, 0, 0), dateTimeOffset.Offset);
}
Note that my asserts are valid in Sweden (CET)
There are a couple of overloads on DateTime.Parse()
Is this useful for your conversion:
[Test]
public void ConvertTimeTest()
{
DateTime dateTime = DateTime.Parse("2012-11-20T00:00:00Z");
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime convertedTime = TimeZoneInfo.ConvertTime(dateTime, cstZone);
Assert.AreEqual(new DateTime(2012, 11, 19, 18, 00, 00), convertedTime);
TimeSpan baseUtcOffset = cstZone.BaseUtcOffset;
Assert.AreEqual(new TimeSpan(0, -6, 0, 0), baseUtcOffset);
}
const String dateString = "2012-11-20T00:00:00Z";
var offsetDate = DateTimeOffset.Parse(dateString);
var offsetDate2 = DateTime.Parse(dateString);
Output is
offsetDate {20-11-2012 0:00:00 +00:00} System.DateTimeOffset
offsetDate2 {20-11-2012 1:00:00} System.DateTime
Related
i am trying to convert current year + 1 midnight date time to unix timestamp.
for that i have tried
DateTime currentTime = DateTime.Today;
DateTime yearEnd = new DateTime( currentTime.Year, 1,1,currentTime.Minute,currentTime.Hour,currentTime.Second,DateTimeKind.Local);
yearEnd = yearEnd.AddYears(1);
double t = (yearEnd.ToUniversalTime() - new DateTime(1970, 1, 1,0,0,0)).TotalMilliseconds;
and above code is returning 1514782800000 i.e. Mon Jan 01 2018 05:00:00 UTC in and Mon Jan 01 2018 10:30:00 Local (india)
what i am expecting is it converts time to Mon Jan 01 2018 00:00:00 local time
By default DateTime creates Unspecified DateTimeKind, so using UTC explicitly helps to avoid confusion. I've tried to rewrite in this way
DateTime currentTime = DateTime.UtcNow;
DateTime yearEnd = new DateTime( currentTime.Year, 1,1,0,0,0, DateTimeKind.Utc);
yearEnd = yearEnd.AddYears(1); // output DateTime has Utc Kind
var unixTimestamp = (yearEnd.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))).TotalMilliseconds;
Console.WriteLine(unixTimestamp);
The output is 1514764800000 which converts to GMT: Monday, 1 January 2018 00:00:00
Update:
In case you need to convert timestamp back to DateTime you may use the following:
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp);
return dtDateTime; // still Utc Kind
}
Usage example if you need to convert to other timezone:
TimeZoneInfo infotime = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time (Mexico)"); // specify your desired timezone here
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(UnixTimeStampToDateTime(unixTimestamp), infotime));
if i understand you right you want the following:
double result = new DateTime(currentTime.Year + 1, 1, 1, 0, 0, 0, DateTimeKind.Local).Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
Or improved for readablity
DateTime newYear = new DateTime(currentTime.Year + 1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime uTSBegin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
double result2 = newYear.Subtract(uTSBegin).TotalSeconds;
I need to convert Cocoa NSDate to C# DateTime and vice versa.
I am using the following method to achieve this:
public static DateTime NSDateToDateTime (Foundation.NSDate date)
{
DateTime reference = TimeZone.CurrentTimeZone.ToLocalTime (
new DateTime (2001, 1, 1, 0, 0, 0));
return reference.AddSeconds (date.SecondsSinceReferenceDate);
}
public static Foundation.NSDate DateTimeToNSDate (DateTime date)
{
DateTime reference = TimeZone.CurrentTimeZone.ToLocalTime (
new DateTime (2001, 1, 1, 0, 0, 0));
return Foundation.NSDate.FromTimeIntervalSinceReferenceDate (
(date - reference).TotalSeconds);
}
But it turns out, this way it is not accounting for Daylight Saving.
Eg. DateTime object in which the time was 5AM in DST returns NSDate with time 6AM.
I'm pretty sure this is an outdated approach. You can cast a NSDate directly to a DateTime now.
Foundation.NSDate nsDate = // someValue
DateTime dateTime = (DateTime)nsDate;
Based on inputs from:
https://forums.xamarin.com/discussion/27184/convert-nsdate-to-datetime
Local Time changes during Daylight Saving.
Hence, always convert to UTC to do the calculations, then convert to Local time if needed.
public static DateTime NSDateToDateTime (Foundation.NSDate date)
{
DateTime reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var utcDateTime = reference.AddSeconds(date.SecondsSinceReferenceDate);
return utcDateTime.ToLocalTime();
}
public static Foundation.NSDate DateTimeToNSDate (DateTime date)
{
DateTime reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var utcDateTime = date.ToUniversalTime();
return Foundation.NSDate.FromTimeIntervalSinceReferenceDate((utcDateTime - reference).TotalSeconds);
}
There is a creepy bug on direct casting to NSDate
My solution was:
public static NSDate DateTimeToNSDate(this DateTime date)
{
var calendar = new NSCalendar(NSCalendarType.Gregorian);
calendar.TimeZone = NSTimeZone.FromName("UTC");
var components = new NSDateComponents { Day = date.Day, Month = date.Month, Year = date.Year, Hour = date.Hour,
Minute = date.Minute, Second = date.Second, Nanosecond = date.Millisecond * 1000000 };
var result = calendar.DateFromComponents(components);
return result;
}
I hope this helps
I've run some tests. Here is my code:
var systemTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var icalTimeZone = iCalTimeZone.FromSystemTimeZone(systemTimeZone);
var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);
var iCalendar = new iCalendar();
var pacificTimeZone = _iCalendar.AddTimeZone(icalTimeZone);
var event = new Event
{
Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
DTStart = new iCalDateTime(2015, 9, 8, 10, 30, 0, pacificTimeZone.TZID, iCalendar),
Duration = new TimeSpan(0, 1, 0, 0)
};
var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");
event.RecurrenceRules.Add(rp);
iCalendar.Events.Add(_event);
var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);
Here's the result:
10 occurences - here are the occurences' Period.StartTime.Value and UTC properties
Value - 9/8/2015 10:30:00 - UTC 9/8/2015 17:30:00
Value - 9/15/2015 10:30:00 - UTC 9/15/2015 17:30:00
Value - 9/22/2015 10:30:00 - UTC 9/22/2015 17:30:00
Value - 9/29/2015 10:30:00 - UTC 9/29/2015 17:30:00
Value - 10/6/2015 10:30:00 - UTC 10/6/2015 17:30:00
Value - 10/13/2015 10:30:00 - UTC 10/13/2015 17:30:00
Value - 10/20/2015 10:30:00 - UTC 10/20/2015 17:30:00
Value - 10/27/2015 10:30:00 - UTC 10/27/2015 17:30:00
Value -11/3/2015 10:30:00 - UTC 11/3/2015 17:30:00 (THIS SHOULD BE 18:30:00!)
Value - 11/10/2015 10:30:00 - UTC 11/10/2015 17:30:00 (THIS SHOULD BE 18:30:00!)
As you can see, the last two should have a UTC time of 18:30:00. So I'm wondering if this is just the way DDay Ical works and I shouldn't count on it getting the UTC datetime right, or if I'm doing something wrong.
You are getting this time difference due to daylight savings. One possible solution is not to get the time zone by name Pacific Standard Time
// First load a file containing time zone information for Pacific Standard Time
var systemTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
In place of this use system time zone like
var systemTimeZone = TimeZoneInfo.GetSystemTimeZones().FirstOrDefault();
Or simply add the local timezone:
iCalendar iCalendar= new iCalendar();
iCalendar.AddLocalTimeZone();
To find all registered timezones, click here
ReadOnlyCollection<TimeZoneInfo> zones = TimeZoneInfo.GetSystemTimeZones();
Console.WriteLine("The local system has the following {0} time zones", zones.Count);
foreach (TimeZoneInfo zone in zones)
Console.WriteLine(zone.Id);
I simply use GetSystemTimeZones() in my code like
public static void Test1()
{
var systemTimeZone = TimeZoneInfo.GetSystemTimeZones().FirstOrDefault();
//TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var icalTimeZone = iCalTimeZone.FromSystemTimeZone(systemTimeZone);
var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);
var iCalendar = new iCalendar();
var pacificTimeZone = iCalendar.AddTimeZone(icalTimeZone);
var _event =
new Event
{
Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
DTStart = new iCalDateTime(2015, 9, 8, 10, 30, 0, pacificTimeZone.TZID, iCalendar),
Duration = new TimeSpan(0, 1, 0, 0)
};
var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");
_event.RecurrenceRules.Add(rp);
iCalendar.Events.Add(_event);
var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);
}
when I debug it got got output like
you can change the time zone accordingly and get the result. Hope it helps you.
Don't use dday.ical; use ical.net.
This should get you started:
var iCalendar = new Calendar();
var start = new DateTime(2015, 9, 8, 10, 30, 0);
var e = new Event
{
Summary = "This is an event at 2015-09-08 10:30 PST (2015-09-08 17:30 UTC)",
DtStart = new CalDateTime(start, "Pacific Standard Time"),
Duration = TimeSpan.FromHours(1)
};
var rp = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20151112T080000Z;WKST=SU;BYDAY=TU");
e.RecurrenceRules.Add(rp);
iCalendar.Events.Add(e);
var startTimeSearch = new DateTime(2015, 9, 8, 0, 0, 0, DateTimeKind.Utc);
var endTimeSearch = new DateTime(2015, 12, 1, 00, 0, 0, DateTimeKind.Utc);
var occurrences = iCalendar.GetOccurrences(startTimeSearch, endTimeSearch);
Results:
I could resolve this. It turns out that you shouldn't specify the time in the ExceptionDates, just add the date component only,
That seems to work, GetOccurances now properly recognizes the exception dates. Hopefully this will help someone going through the same pain.
I'm trying to convert this unix timestamp
1415115303410
in DateTime, in this way:
private static DateTime UnixTimeStampToDateTime(long unixTimeStamp)
{
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp);
return dtDateTime;
}
But I get a wrong date:
Date: {04/11/0045 00:00:00}
NOTE: dtDateTime.AddSeconds(unixTimeStamp) throws an exception.. my number is in Milliseconds.
with this online conversion tool http://www.epochconverter.com/ I get the right conversion:
04/11/2014 15:35:03 GMT+0:00
How I can convert this one?
Your code is working just fine, as is. Here is a fiddle.
Everyone that is telling you to use AddSeconds is wrong. The number you are giving us is clearly in milliseconds. There are 31,536,000 seconds in a year. 1415115303410 divided by 31536000 is 4487. There hasn't been 4,487 years passed since 1/1/1970.
use AddSeconds instead of AddMilliseconds
private static DateTime UnixTimeStampToDateTime(long unixTimeStamp)
{
System.DateTime dtDateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp);
return dtDateTime;
}
Just use DateTimeOffset
DateTimeOffset date = DateTimeOffset.FromUnixTimeSeconds(1415115303410)
public DateTime FromUnixTime(long unixTime)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddMilliseconds(unixTime);
}
var date = FromUnixTime(1415115303410); // 11/4/2014 3:35:03 PM
Since your number is in milliseconds, Unix time, use AddMilliseconds.
Try This
DateTime date = new DateTime(Convert.ToInt64("1415115303410"));
Microsoft continue thinking about us! All solutions to add seconds/milliseconds is not working with Visual Studio 2017 (.Net 4.6.1). But there is a new solution:
public static DateTime numStrToDate(String val)
{
DateTime dRet = new DateTime(1970, 1, 1, 0, 0, 0, 0);
long dSec;
if (long.TryParse(val, out dSec))
{
TimeSpan ts = new TimeSpan(dSec*10l);
dRet = dRet.Add(ts);
}
return dRet;
}
If you need a UTC time - just add 'System.DateTimeKind.Utc' to the DateTime constructor call.
Date to Timestamp
DateTime date = DateTime.ParseExact(date_string, "dd/MM/yyyy H:mm:ss", null);
Double timestamp = Math.Truncate((date.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
Timestamp to Date
DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Unspecified);
dtDateTime = dtDateTime.AddSeconds(Double.Parse(arrayFinalResponse[i, 5])).ToLocalTime();
String date = dtDateTime.ToString("dd/MM/yyyy H:mm:ss", CultureInfo.GetCultureInfo("en-US"));
You can do the conversion by using a little trick with date command.
It does depend on your timezone. I live in UTC + 1 so for me it is like this:
h1x1binax:~ # date -d "Thu Jan 1 01:00:00 CET 1970 + 1415115303410 second"
Thu Mar 21 09:16:50 CET 46813
h1x1binax:~ #
So that's not a unixtime timestamp ... it is probably in milliseconds so need to divide by 1000
h1x1binax:~ # date -d "Thu Jan 1 01:00:00 CET 1970 + 1415115303 second"
Tue Nov 4 16:35:03 CET 2014
h1x1binax:~ #
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm trying to add the phones current time to my date time list. I need it to be able to subtract with the ticks. I have tried using phonecurrentime.ToString("dd hh:mm"); but because it's a string there are no ticks and all sorts of errors!
I need it to work with DateTime.now.
Here is my code:
InitializeComponent();
List<DateTime> theDates = new List<DateTime>();
DateTime fileDate, closestDate;
theDates.Add(new DateTime(2000, 1, 1, 10, 29, 0));
theDates.Add(new DateTime(2000, 1, 1, 3, 29, 0));
theDates.Add(new DateTime(2000, 1, 1, 3, 29, 0));
// This is the date that should be found
theDates.Add(new DateTime(2000, 1, 1, 4, 22, 0));
// This is the date you want to find the closest one to
fileDate = DateTime.Now;
long min = long.MaxValue;
foreach (DateTime date in theDates)
{
if (Math.Abs(date.Ticks - fileDate.Ticks) < min)
{
min = Math.Abs(date.Ticks - fileDate.Ticks);
closestDate = date;
}
}
Darren Davies above is correct.
You can add/subtract datetime objects. The result is of type TimeSpan, which lets you easily compare date and/or time differences.
Also, you should give a name to each date you add to your list (assign to a variable then add to list). A month later you won't remember what each day meant ;)
if you have a string and want to convert it to DateTime you can use
CultureInfo cf = new CultureInfo("en-us");
if(DateTime.TryParseExact("12 12:45", "dd hh:mm", cf, DateTimeStyles.None, out fileDate))
{
// your code
}
and your code would look like:
List<DateTime> theDates = new List<DateTime>();
DateTime fileDate, closestDate;
theDates.Add(new DateTime(2000, 1, 1, 10, 29, 0));
theDates.Add(new DateTime(2000, 1, 1, 3, 29, 0));
theDates.Add(new DateTime(2000, 1, 1, 3, 29, 0));
// This is the date that should be found
theDates.Add(new DateTime(2000, 1, 1, 4, 22, 0));
CultureInfo cf = new CultureInfo("en-us");
string timeToParse = phonecurrentime.ToString("dd hh:mm");
if(DateTime.TryParseExact(timeToParse, "dd hh:mm", cf, DateTimeStyles.None, out fileDate))
{
long min = long.MaxValue;
foreach (DateTime date in theDates)
{
if (Math.Abs(date.Ticks - fileDate.Ticks) < min)
{
min = Math.Abs(date.Ticks - fileDate.Ticks);
closestDate = date;
}
}
}
if you want to compare the time part of the dateTime you can use TimeOfDay property:
TimeSpan ts = DateTime.Now.TimeOfDay;
foreach (DateTime date in theDates)
{
long diff = Math.Abs(ts.Ticks - date.TimeOfDay.Ticks);
if (diff < min)
{
min = diff;
closestDate = date;
}
}
fileDate = phonecurrentime.ToString("dd hh:mm");
Will not compile. fileDate is a DateTime object. You need to assign it to another DateTime object, not a string.
If phonecurrenttime is a DateTime you can ommit the .ToString() method.
fileDate = phonecurrenttime;
Edit
From your comment, if you simply want to assign the current ddate/time to fileDate you can use DateTime.Now:
fileDate = DateTime.Now;