Converting DateTime in UTC to my "local" time? - c#

I am working with a MongoDB trying to deserialize a BsonDate to a DateTime with the proper Kind. When a DateTime is serialized to MongoDB it is saved in UTC format, when it is deserialized it is returned as a UTC format too.
My issue is that I cannot seem to be able to convert the DateTime I am given back from Mongo to my local DateTime (UTC to EST). I am pretty sure I can get around my issue by just removing the UTC time offset (AddHours) for my timezone but I am pretty sure that DateTime can do this for me and would handle any time zone the application is ran in.
// Deserializing the DateTime object
DateTime eventTimeStamp = (DateTime)aDoc[MongoStrings.Log_Field_TimeStamp];
Console.Out.WriteLine("UtcDate: " + eventTimeStamp);
Console.Out.WriteLine("Locale : " + eventTimeStamp.Kind);
// First attempt at conversion
DateTime localTime = DateTime.SpecifyKind(eventTimeStamp, DateTimeKind.Local);
Console.Out.WriteLine("NewTime: " + localTime);
Console.Out.WriteLine("Locale : " + localTime.Kind);
// Another attempt at conversion
DateTime localTime2 = new DateTime(eventTimeStamp.Ticks, DateTimeKind.Local);
Console.Out.WriteLine("NewTim2: " + localTime2);
Console.Out.WriteLine("Locale : " + localTime2.Kind);
The code above produces the following output
UtcDate: 1/29/2016 2:54:05 PM
Locale : Utc
NewTime: 1/29/2016 2:54:05 PM
Locale : Local
NewTim2: 1/29/2016 2:54:05 PM
Locale : Local
My local time when that log was produced is 9:54:05 AM.

This might work for you:
// This is your code
// Deserializing the DateTime object
DateTime eventTimeStamp = (DateTime)aDoc[MongoStrings.Log_Field_TimeStamp];
Console.Out.WriteLine("UtcDate: " + eventTimeStamp);
Console.Out.WriteLine("Locale : " + eventTimeStamp.Kind);
// This is new code
Console.Out.WriteLine("LocalDate: " + eventTimeStamp.ToLocalTime());
The reasoning would be that your localTime variables are set to the exactly same time stamp as the one in UTC, you just say that it should be taken as a local time. But this setting as local time does no conversion of times, it just says what kind of time this is so that other methods (like ToLocalTime) know what to do ...
If you want that local time in a variable, then it might be like this:
DateTime localTime = eventTimeStamp.ToLocalTime();
And I guess it will work without setting the kind. If not, you know how to set the kind ...

Related

JavaScriptSerializer :After serialization Date becomes less by one day [duplicate]

I am using JavaScriptSerializer for serializing DateTime, but when I deserialize it show one day less from the date it get serialize:
Here is test:
DateTime startDate=new DateTime(2012,1,20);//set the 20th of January
JavaScriptSerializer serializer=new JavaScriptSerializer();
string serializeDate= serializer.Serialize(startDate);
DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);//I get 19th of Jan
Assert.Equals(startDate, afterDeserialize);
firstly I thougt it because of javascript datetime format but as I know for javascript Month is zero index 0=January, but I am getting one day less than the original date.
It's not losing a day arbitrarily, it's converting to a UTC date (or I should say using the date in a UTC date format) so when it's unserialized it you're no longer within your personal time zone. It's basically performing:
DateTime whateverDate = /* incoming date */;
long ticks = whateverDate.ToUniversalTime() // make UTC
.Subtract(new DateTime(1970, 1, 1)) // subtract UNIX Epoch
.TotalMilliseconds(); // get milliseconds since then
// push in to the "\/Date(ticks)\/" format
String value = String.Format(#"\/Date({0})\/", ticks);
However, try the following:
// or you rely on it serializing, then bring it back to your own local time
// (apply the time zone).
afterDeserialize = afterDeserialize.ToLocalTime();
You'll now have the UTC time back to your local time (with time zone applied).
To Pass your test:
DateTime startDate = new DateTime(2012,1,20);
JavaScriptSerializer serializer = new JavaScriptSerializer();
String serializeDate = serializer.Serialize(startDate);
DateTime afterDeserialize = serializer.Deserialize<DateTime>(serializeDate)
.ToLocalTime(); // Note: this is added
Assert.Equals(startDate, afterDeserialize); // pass!
I had the same problem and solved it by using
Newtonsoft.Json.JsonConvert.SerializeObject()
instead of
new System.Web.Script.Serialization.JavaScriptSerializer().Serialize().
The latter call stores your DateTime converted to some random timezone (GMT+0 seems to be hardcoded).
On deserializing JavaScriptSerializer giving me output in UTC (Universal Time) which due to change in hours change the date. As Brad Christie suggested to change DateTime to UTC it can solve the problems.
But actually there is no need to change the:
DateTime startDate = new DateTime(2012, 1, 20).ToUniversalTime();
as it is already taking it as Universal Time. So I just convert the output of deserialize to LocalTime:
DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);
afterDeserialize.ToLocalTime();
it solved the issue.

C# Converting string to DateTime without using DateTimeOffset

I'm trying to bring over facebook events to my website. They will be coming from different regions. For example, an event is in Eastern Time (-4 hours difference from UTC) and my local time is Central time (-5 hours difference from UTC).
I am calling their graph API from a console app. I get the date of the events like this:
// get event items
me = fbClient.Get(url);
var startTime = me["start_time"];
var endTime = me["end_time"];
the start time shows: "2017-04-30T13:00:00-0400" object {string}
When I try to convert that string into a DateColumn type, it changes the output time to:
var dateTime = Convert.ToDateTime(startTime);
{4/30/2017 12:00:00 PM}
It shifted the hour from 13 -> 12, how do I convert the string into date using DateTime and not using DateTimeoffset?
This examples shows how to do it using DateTimeOffset, but I need mine in DateTime type?
https://stackoverflow.com/a/19403747/1019042
You can use the DateTime property of DateTimeOffset like the answer accepted in the link you've provided.
Or, if you really like to do it just with DateTime you can if you cut the timezone from the string:
var dt = DateTime.ParseExact(startTime.Substring(0,19),
"yyyy-MM-ddTHH:mm:ss",
CultureInfo.InvariantCulture);

Strange behavior from DateTime objects

I do the following:
var now = DateTime.Now;
var utc = DateTime.UtcNow;
var timeSpan = now - utc;
Console.WriteLine("Now is: " + now.ToString("yyyy-MM-dd HH:mm:ss:ms") + " utc is: " + utc.ToString("yyyy-MM-dd HH:mm:ss:ms") + " timeSpan: " +
timeSpan.TotalMinutes);
Console.ReadKey();
It gives the following result:
And if I take the timespan.hours (which is the one I actually use) it revelas 1?
Should be 2 What am I doing wrong there?
There is some time passes between you get times (system can even switch processes between these two calls):
var now = DateTime.Now;
// some time passes here
var utc = DateTime.UtcNow;
Thats why you have less than 2 hours between two values. You should get time only once and then convert it to local time:
var utc = DateTime.UtcNow;
var now = utc.ToLocalTime();
// timeSpan: 120
Or use TimeZoneInfo.ToUniversalTime to convert local time to UTC time:
var now = DateTime.Now;
var utc = TimeZone.CurrentTimeZone.ToUniversalTime(now);
The reason is simple: your calculation introduces an error by taking the time twice. The final result is slightly wrong, but the time taken to make the calls.
The solution is simpler.
Console.WriteLine(TimeZoneInfo.Local.BaseUtcOffset.Hours);
Console.WriteLine(TimeZoneInfo.Local.GetUtcOffset(DateTime.Now).Hours);
There is no need to get or convert times when what you actually want is time zone info. The first line gets the "normal" local time offset; the second gets the offset for 'now' in case your timezone is subject to daylight saving or other adjustments.

Get Current DateTime C# without hour

Hi I currently have a TimePicker. It returns an object TimeSpan.
What I need to do is to set a DateTimeOffset that is equal to current date plus the TimeSpan from the TimePicker.
How can I actually get the current DateTimeOffset.now that doesn't have a Time on it, only the Date so that I can add the offset to it.
Thanks
As in DateTime object you have a Date property, it returns date part without time (it means time is 00:00:00).
DateTime today = DateTimeOffset.Now.Date;
DateTime result = today + yourTimeSpan;
With this solution will lost Offset information (because Date is a DateTime). To keep it you just need to subtract time part:
DateTimeOffset now = DateTimeOffset.Now;
DateTimeOffset result = now - now.Time + yourTimeSpan;
Or with constructor:
DateTimeOffset now = DateTimeOffset.Now;
DateTimeOffset result = new DateTimeOffset(now.Date + yourTimeSpan, now.Offset);
Can you not just .Date it?
var a = DateTimeOffset.Now.Date;
try using:
DateTime.Today
instead of Now.

Convert datetime entered by user to UTC

The user enters a date and a time in separate textboxes. I then combine the date and time into a datetime. I need to convert this datetime to UTC to save it in the database. I have the user's time zone id saved in the database (they select it when they register). First, I tried the following:
string userTimeZoneID = "sometimezone"; // Retrieved from database
TimeZoneInfo userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneID);
DateTime dateOnly = someDate;
DateTime timeOnly = someTime;
DateTime combinedDateTime = dateOnly.Add(timeOnly.TimeOfDay);
DateTime convertedTime = TimeZoneInfo.ConvertTimeToUtc(combinedDateTime, userTimeZone);
This resulted in an exception:
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
I then tried setting the Kind property like so:
DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Local);
This didn't work, so I tried:
DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Unspecified);
This didn't work either. Can anyone explain what I need to do? Am I even going about this the correct way? Should I be using DateTimeOffset?
Just like all the other methods on DateTime, SpecifyKind doesn't change an existing value - it returns a new value. You need:
combinedDateTime = DateTime.SpecifyKind(combinedDateTime,
DateTimeKind.Unspecified);
Personally I'd recommend using Noda Time which makes this kind of thing rather clearer in my rather biased view (I'm the main author). You'd end up with this code instead:
DateTimeZone zone = ...;
LocalDate date = ...;
LocalTime time = ...;
LocalDateTime combined = date + time;
ZonedDateTime zoned = combined.InZoneLeniently(zone);
// You can now get the "Instant", or convert to UTC, or whatever...
The "leniently" part is because when you convert local times to a specific zone, there's the possibility for the local value being invalid or ambiguous in the time zone due to DST changes.
You can also try this
var combinedLocalTime = new DateTime((dateOnly + timeOnly.TimeOfDay).Ticks,DateTimeKind.Local);
var utcTime = combinedLocalTime.ToUniversalTime();

Categories

Resources