Timezone issue with UIDatePicker Date: 1 Hour Wrong - c#

I'm having an issue with the Monotouch UIDatePicker being 1 hour behind. I think this is to do with Time Zones or something similar. I've tried explicitly setting the TimeZone and Locale of my UIDatePicker but this doesn't seem to be helping.
datePicker.Locale = NSLocale.CurrentLocale;
datePicker.TimeZone = NSTimeZone.LocalTimeZone;
In the ValueChanged handler the following line returns a value 1 hour earlier than the time selected in the user interface:
var date = DateTime.SpecifyKind((s as UIDatePicker).Date, DateTimeKind.Local).ToLocalTime();
In the ValueChanged Handler I've double checked that the Locale and TimeZone is the same as what was set. The TimeZone is Europe/Dublin and Locale en_US.
This information was retrieved by:
datePicker.Locale.LocaleIdentifier;
datePicker.DatePicker.TimeZone;
Is there another step I'm missing?
Thanks!

The date returned from DatePicker is in UTC format. There are several methods of converting UTC to local time. As this answer states ToLocalTime is the best one.
DateTime.SpecifyKind(datePicker.Date, DateTimeKind.Utc).ToLocalTime();

After var date = DateTime ..., add the following:
if (date.IsDaylightSavingTime ())
date = date.AddHours (1);

This magical code fixed all my problems with daylight savings and timezones. Write if you need help.
NSDate sourceDate = date;
NSTimeZone sourceTimeZone = new NSTimeZone ("UTC");
NSTimeZone destinationTimeZone = NSTimeZone.LocalTimeZone;
int sourceGMTOffset = sourceTimeZone.SecondsFromGMT (sourceDate);
int destinationGMTOffset = destinationTimeZone.SecondsFromGMT (sourceDate);
int interval = destinationGMTOffset - sourceGMTOffset;
var destinationDate = sourceDate.AddSeconds (interval);
var dateTime = new DateTime(2001, 1, 1, 0, 0,0).AddSeconds(destinationDate.SecondsSinceReferenceDate);
DescriptionLabel.Text = dateTime.ToString ("dd.MM.yyyy. HH:mm");
this.date = destinationDate;

Related

What are valid UTCDateTime type string formats for AIF transfomrmations?

Im am trying to write a .net class that transforms a piece of xml to a AX UtcDateTime type.
The class is used in an inbound transformation.
Original xml:
<DateTime>
<Date>2014-06-12</Date>
<Time>10:52:00</Time>
<Zone>+02:00</Zone>
</DateTime>
My resulting xml leads to an exeption in the exeptionlog:
"The value '2014-06-12T12:52:00+02:00' is not a valid UtcDateTime type."
I think AIF expect the Z at the end of the value, and I am not sure if the localDateTime is mandatory and or if the milliseconds are a requirement.
I would like to know how the UtcDateTime field in transformed xml should be formatted to be accepted by AIF.
Like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00+02:00">2014-06-12T08:52:00Z</MessageHeaderDateTime>
or like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00.1108723+02:00">2014-06-12T08:52:00.1108723Z</MessageHeaderDateTime>
or are other things missing?
My Code
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc);
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
DateTime netdttmoffset = netdttm.Subtract(timespan);
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
datetime.localDateTimeSpecified = true;
I use a similar appraoch for the case where I use utcnow.
Problem i that I have limited testing possibilities due to hot-swapping being disbled in the environment where I have to develop my code. So I would like to be certainin about the formatting.
Thanx for your help.
I finally got it to work. My solution:
//declare the AX utcdatetime type from the cs class generate with:
//xsd C:\...\SharedTypes.xsd C:\..\AIFschema.xsd /Classes /Out:C:\location\of\csfile\
AxType_DateTime datetime = new AxType_DateTime();
//Ax store the time in GMT with an optional local time. My XML can have any timezone.
datetime.timezone = AxdEnum_Timezone.GMT_COORDINATEDUNIVERSALTIME;
//I set this to false as i am not interested in actually storing the local time. Plus AX fails over the formatting .net returns.
datetime.timezoneSpecified = false;
//{... left out code to retrieve the hours, minutes etc from my XML}
//declare the .net datetime variable with the values from the xml:
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc);
DateTime netdttmoffset = new DateTime();
// (optional field) <zone>+01:00</zone>
if (message.Header.DateTime.Zone != null)
{
{... left out code to retrive zone offset info from xml}
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
netdttmoffset = netdttm.Subtract(timespan);
}
else //no zone, so datetime == GMT datetime.
{
netdttmoffset = netdttm;
}
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
//do not output to xml, or AX will fail over this.
datetime.localDateTimeSpecified = false;
Result xml snippet as accepted by AX:
<MessageHeaderDateTime>2014-07-30T16:41:10.001Z</MessageHeaderDateTime>
I found this to be easier. If you want a particular datetime, say Jan 31, 2015 8:00 am, to be stored in AX, the .net code to make it happen would be
DateTime utcDateTime = new DateTime(2015, 1, 31, 8, 0, 0).ToUniversalTime();
var workerStartDate = new AxdExtType_HcmEmploymentStartDateTime
{
Value = utcDateTime
};
The XML generated would be would be <WorkerStartDate>2015-05-12T13:00:00Z</WorkerStartDate>, assuming you are 5 hours behind GMT on the computer that runs the .net code. The AX database will store the value 2015-05-12T13:00:00Z as well.
<dyn:StartDate>2014-06-22T00:00:00.000+02:00</dyn:StartDate>
This format always does the trick for me. (Notice the ms)

DateTime.AddYear, AddMonth, AddDay, AddHour, AddMinute doesn't add?

I have the following code:
DateTime endTime = new DateTime(01, 01, 01, 00, 00, 00);
endTime = endTime.AddYears(currentYear - 1);
endTime = endTime.AddMonths(currentMonth - 1);
endTime = endTime.AddDays(currentDay - 1);
hourToWaitTo = Convert.ToInt32(txtboxHourToWaitTo.Text);
minuteToWaitTo = Convert.ToInt32(txtboxMinuteToWaitTo.Text);
endTime = endTime.AddHours(hourToWaitTo);
endTime = endTime.AddMinutes(minuteToWaitTo);
But it doesn't add anything to endTime
EDIT1:
I set currentYear, currentMonth and currentDay like this:
int currentYear = Convert.ToInt32(DateTime.Now.ToString("yyyy"));
int currentMonth = Convert.ToInt32(DateTime.Now.ToString("MM"));
int currentDay = Convert.ToInt32(DateTime.Now.ToString("dd"));
hourToWaitTo and minuteToWaitTo is set by user in a textbox.
I want the user to set a time (e.g. 12:25) for the computer to shutdown at, and I also want a countdown to say how many hours:minutes:seconds left till shutdown. I have managed to do all of this, but i couldn't fix the above mentioned endTime problem.
SOLUTION:
The solution to this problem is very simple:
DateTime endTime = new DateTime(currentYear, currentMonth, currentDay, hourToWaitTo, minuteToWaitTo, 0);
I tried to do this earlier, but for some reason I was getting an error. To set those variables above I used:
int currentYear = Convert.ToInt32(DateTime.Now.ToString("yyyy"));
int currentMonth = Convert.ToInt32(DateTime.Now.ToString("MM"));
int currentDay = Convert.ToInt32(DateTime.Now.ToString("dd"));
and
int minuteToWaitTo = Convert.ToInt32(txtboxMinuteToWaitTo.Text);
int hourToWaitTo = Convert.ToInt32(txtboxHourToWaitTo.Text);
Thank you all for your help.
This is not a direct answer to your question - the code you've posted looks okay so there must be something else going on - but I'm wondering why you don't just do something like:
hourToWaitTo = Convert.ToInt32(txtboxHourToWaitTo.Text);
minuteToWaitTo = Convert.ToInt32(txtboxMinuteToWaitTo.Text);
DateTime endTime = new DateTime(currentYear, currentMonth, currentDay, hourToWaitTo, minuteToWaitTo, 0);
Code like this should be abolished:
int currentYear = Convert.ToInt32(DateTime.Now.ToString("yyyy"));
int currentMonth = Convert.ToInt32(DateTime.Now.ToString("MM"));
int currentDay = Convert.ToInt32(DateTime.Now.ToString("dd"));
You are checking the system clock three times, pulling out partial values, serializing to a string, parsing that string, and then using each part. Lots of work for nothing.
All you really need is:
DateTime endTime = DateTime.Today.AddHours(hourToWaitTo)
.AddMinutes(minuteToWaitTo);
You should consider the kind of the dates you are working with. When you construct a DateTime using the constructors, you are getting a .Kind of Unspecified unless you specifically tell it what kind of date you want. It's more appropriate in your scenario to be working with a local date, which you will get with DateTime.Today or DateTime.Now.
Also be aware that since you are asking the user for a local time, but allowing them to enter the time components, that time may be invalid or ambiguous. This happens during daylight savings time transitions. You can validate the user input with TimeZoneInfo.Local.IsInvalidTime() or TimeZoneInfo.Local.IsAmbiguousTime(). In the case of ambiguous time, you will need to ask your user "Before or after the daylight savings transition?" or something similar.
And finally, if there's any chance that the user is NOT in the same timezone as the computer in question, then you have a lot of more work to do. You should consider using DateTimeOffset instead, and you will need to capture the intended offset or timezone of the shutdown. Another approach would be to convert the time to the UTC time of the shutdown event. Review this article for more details and best practices.
new DateTime(year,month,day,hour,minute,0)
?

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();

How to set current time to a value

I was just wondering if there is a way to get the current time and set it into a value.
If its 12:06 AM.. I want to get that time and set it into currentTime.
Example
float currentTime = 0;
currentTime = 12.06;
As others have mentioned, the DateTime class would be ideal for this, and to work out the difference between 2 date/times:
DateTime end = DateTime.Now;
DateTime start = new DateTime(2011, 12, 5, 12, 6,0);
double hours = (end - start).TotalHours;
The subtraction of DateTime objects results in a TimeSpan object that you can use to see the hours/minutes etc.
try DateTime class
DateTime dt = DateTime.Now;
Is this what you're looking for?
DateTime currentTime;
currentTime = DateTime.Now;
Don't use floats or strings. You can do all kinds of cool things using DateTime.
Here's how you'd get the hours that someone worked:
var clockIn = new DateTime(2011,12,4,9,0,0); // December 4th, 9 AM
var clockOut = new DateTime(2011,12,4,17,0,0); // December 4th, 5 PM
var duration = clockOut - clockIn; // TimeSpan
Console.Write(duration.TotalHours); // 8
A few people have mentioned how, but as a 'better' recommendation you should use
DateTime currentTime = DateTime.UtcNow
Otherwise you have issues when the clocks go back, if your timing code is run on those days. (plus it is far easier to alter the UTC time to local time than it is to convert a '1am' to UTC (as there will be two of them when the clocks go back)
Well if you really what it as a float then try:
var currentDate = DateTime.Now;
float currentTime = float.Parse((currentDate.Hour > 12 ? currentDate.Hour -12 :
currentDate.Hour) + "." + currentDate.Minute);
I wouldn't recommend comparing dates or time with floats. A better options would be to use timespans.
You should be using a Timespan instance for time related values, you can use the flexibility to get the required values like
TimeSpan ts = DateTime.Now.TimeOfDay;
ts.ToString("hh:mm") // this could be what you are looking for
You could then use ts.TotalHours which would give you fractional hours (as a double) else you could construct a string specifically using ts.Hours ..ts.Minutes play around and it could be prove useful.
Try the following:
DateTime StartTime=StartTime value;
DateTime CurrentTime=DateTime.Now;
TimeSpan dt = CurrentTime.Subtract(StartTime);
In dt you will get a working time period.
If you want to have the difference between two times, then do this:
DateTime dateOne = DateTime.Parse(enteredTime);
DateTime dateTwo = DateTime.Now;
TimeSpan difference = dateOne - dateTwo;

How do I get the current date in a user's timezone, given an TimeSpan offset?

I need to find what day it is for a user given a Timespan offset.
Right now, this is what I have tried:
string timezone = this.HttpContext.Request.Headers["X-MyApp-Timezone"];
var timeSpan = TimeSpan.Parse(timezone, DateTimeFormatInfo.InvariantInfo);
var consumersCurrentTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeSpan);
var consumersCurrentDate = consumersCurrentTime.Date();
Which I know doesn't work because TimeZoneInfo.ConvertTimeFromUtc takes a TimeZoneInfo not a TimeSpan. I looked into it a little and found that it's impossible given an offset to get the entire Time Zone information, but I really don't need to know the exact time zone, just what day it is. Is there any way for me to do this?
string timezone = this.HttpContext.Request.Headers["X-MyApp-Timezone"];
DateTime consumersCurrentDateTime = DateTime.UtcNow + TimeSpan.Parse(timezone,
DateTimeFormatInfo.InvariantInfo);
DateTime customersCurrentDate = consumersCurrentDateTime.Date;
Thanks to Joao Paulo's comment, I think I can do this without involving time zones at all, just by doing this:
string timezone = this.HttpContext.Request.Headers["X-MyApp-Timezone"];
var timeSpan = TimeSpan.Parse(timezone, DateTimeFormatInfo.InvariantInfo);
var consumersCurrentDate = DateTimeOffset.UtcNow.ToOffset(timeSpan).Date;

Categories

Resources