UIDatePicker return wrong NSDate - iphone

I am using UIDatePicker in my app and when i take the date that was chosen with:
NSDate *date = picker.date;
picker.date returned the day before the date that I chose.
any idea why it happens?

UIDatePicker will be displaying dates and times in your local timezone. However, NSDate does not have any concept of a timezone as it stores an absolute number of seconds since a reference date. When NSLogging a date, it shows the date and time in GMT. I expect if you work out your local timezone difference from GMT, you will see that it is the correct date.
Try creating an NSDateFormatter or NSCalendar with the appropriate locale and pass the date through that.
For further reading on this common topic, see this site written by another SO contributor.

give this a try worked for me
NSDate* sourceDate = [NSDate date];
NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;
NSDate* destinationDate = [[[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate] autorelease];
//i'm outputting mine in a label you can use anything you like
NSString *dateOutput = [[[NSString alloc] initWithFormat:#"%#", destinationDate]autorelease];
self.dateLabel.text = dateOutput;

Remember to create the NSDate and then output it with a valid timezone and calendar!
NSDate only represents an absolute point in time. It has no concept of timezone (NY, Barcelona, ...) or calendar (Gregorian, Hebrew, ...).
UIDatePicker returns by default a NSDate with the system NSCalendar and NSTimeZone, but when you try to print it later, you do not format the output. You may have there the mismatch.
So 1st you need to setup the UIDatePicker correctly and 2nd transform the output with the NSDateFormatter so it knows the Calendar and the TimeZone being used.
An example code with the init of the UIDatePicker and then printing the result:
- (void)viewDidLoad
{
[super viewDidLoad];
// init the UIDatePicker with your values
// by default UIDatePicker inits with today, system calendar and timezone
// Only for teaching purposes I will init with default values
NSDate * now = [[NSDate alloc] init];
[_datePicker setDate: now]
animated: YES];
_datePicker.timeZone = [NSTimeZone localTimeZone];
_datePicker.calendar = [NSCalendar currentCalendar];
[_datePicker addTarget: self
action: #selector(getDatePickerSelection:)
forControlEvents:UIControlEventValueChanged];
}
-(void)getDatePickerSelection:(id) sender
{
// NSDateFormatter automatically inits with system calendar and timezone
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// Setup an output style
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
// Medium style date, short style time => "Nov 23, 1937 3:30pm"
NSString *dateString = [dateFormatter stringFromDate:date];
}
Check the answer I did for another very similar question:
NSDate output using NSDateFormatter

Did you check the timezone?
When you print an NSDate it will use GMT as it timezone.
If you set the system timezone to the NSDateFormatter you might get an other date, because it will take the timezone and calculate the time accordingly.
Add this code and see if the output is correct:
NSDate *date = picker.date;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:NSDateFormatterNoStyle];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSLog(#"Date: %#", [dateFormmater stringFromDate:date]);
[dateFormatter release], dateFormatter = nil;

Just add one line of code
self.datePicker.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
0 is for GMT 00 . Add according to your time zone.

Related

Calculate date and time corresponding to different timezone

I have an ipad application that draws a graph with time on y-axis. Now my problem is that, this same graph by a user can be accessed anywhere in the world. But then the time on the graph should be adjusted so that it should correspond to the current timezone of the user. So the time on the graph should compensate for any difference in time between timezones. Can anyone tell me how to take the timezone from current device and calculate the offset time if i am passing the timezone of the device from which the graph is sent.
This is my date formatting function. I intend to pass the timezone also along with the date.
+(NSDate *)DateUKFormatFromString:(NSString *)date
{
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init] ;
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_GB"];
[dateFormatter setLocale:locale];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
NSDate* returnDate = [dateFormatter dateFromString:date];
return returnDate;
}
Thanks in advance.
there is a dateFormatter instance method setTimeZone: use it like this
[NSTimeZone resetSystemTimeZone];
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
For information on the two methods, please read documentation. Hope it helps. Cheers
Edit:
If date coming from server is for a specific time Zone (time zone of the server). Then you will need to get the timeZone
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:"Server timezone name"];
NSInteger serverDifference = [timeZone secondsFromGMT];
[NSTimeZone resetSystemTimeZone];
NSTimeZone *systemTimeZone = [NSTimeZone systemTimeZone];
NSInteger systemDifference = [systemTimeZone secondsFromGMT];
NSInteger difference = systemDifference - serverDifference;
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:difference]];
try this in case you are not getting a 0 GMT difference time from server.
+(NSDate *)DateUKFormatMonthFromString:(NSString *)date AndTimeZoneName:(NSString *) timeZoneName
{
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"MM/dd/yyyy HH:mm:ss"];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:timeZoneName];
[formatter setTimeZone:timeZone];
NSDate *date1 = [formatter dateFromString:date];
[formatter setTimeZone:[NSTimeZone systemTimeZone]];
return date1;
}
In the end, this worked for me... Seems that iOS will take care of time zone differences on its own...!!!

Save the current time when event is performed

In my app i am using zbar sdk to scan ticket and i want to save current time in sqlite when the camera takes the shot . How can i do this.
Thanks in advance.
Following code use for the getting the device local current time.
NSDate* sourceDate = [NSDate date];
NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;
NSDate* destinationDate = [[[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate] autorelease];
May this Helping a lot for coding
You can write something like this:
NSDate *currentTime = [NSDate date];
Then you can extract appropriate values from NSDate object by using NSDateComponents or NSDateFormatter, if you need.
when you click save on ZBarReaderController , this bellow method called..
- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
{
NSDate *currentDateandTime = [NSDate date];
/// and save this date and time in your database
////with date formate see bellow my edited answer
/// this for get string from date with formate
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEE, dd-MM-yyyy hh:mm:ss a"];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(dateString);
/// for get date from string with different formate use bellow code
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"EEE, d MMM yyyy HH:mm:ss z"];
NSDate *date = [dateFormatter dateFromString: dateString];
}
also for more detail about NSDate see my blog on bellow link..
http://parasjoshi3.blogspot.in/2012/01/convertstringtodatedatetostring.html
i hope this help you...
:)

NSDateFormatter - does not respect 12/24 hour (am/pm) system setting in some circumstances

I want to output a date (that has relative dates, e.g. Today, Yesterday etc.) and time (respecting the 12/24 hours setting on the iOS device) E.g.
Today 5:48 PM (when in 12 hour mode); and
Today 17:48 (when in 24 hour mode)
Configuring an NSFormatter like this (and using stringFromDate:) does not work:
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle]; // doesn't respect am/pm setting on iOS device (grrr!)
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // but does get relative dates
This gives you relative dates, but defaults to the 12/24 setting for the locale, e.g. 12 hours for US and 24 hours for UK. (Why Apple think UK people like 24 hours clocks, I don't know...)
A work around that I've adopted uses two NSDateFormatters, one for the date and one for the time. It appears that when you configure an NSDateFormatter with a dateStyle of NSDateFormatterNoStyle and a timeStyle of NSDateFormatterShortStyle, then it does respects the 12/24 hour setting. (So it's just when you have BOTH date and time styles set that there is trouble.)
I've included my work around below in case anyone else has a similar issue. Is there an easier way to do this? The work around seems somewhat awkward and it is not clear how confident I should be it will continue working in future revisions of iOS.
Work around
- (NSString*) humanRelativeDateAndTimeAlt: (NSDate*) date;
{
NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle]; // no time for this formatter
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // relative dates
NSString* datePart = [[self relativeDateFormatter] stringFromDate:date];
NSDateFormatter* timeDateFormatter = [[NSDateFormatter alloc] init];
[timeDateFormatter setLocale:[NSLocale autoupdatingCurrentLocale]];
[timeDateFormatter setDateStyle: NSDateFormatterNoStyle]; // no date for this formatter
[timeDateFormatter setTimeStyle: NSDateFormatterShortStyle]; // does respect 12/24 hour setting
NSString* timePart = [timeDateFormatter stringFromDate:date];
int skipZero = 0; // extra code to remove leading zero if present
if ([[timePart substringToIndex:1] isEqualToString:#"0"]) skipZero = 1;
[relativeDateFormater release];
[timeDateFormatter release];
return [NSString stringWithFormat:#"%# %#", datePart, [timePart substringFromIndex:skipZero]];
}
The reason for this behaviour is Locale, set the correct Locale, Set the local of your NSDateFormatter to en_US_POSIX will fix this.
It works for both 24-hour and 12 hour format.
From Apple doc:
On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set.
Reference: What is the best way to deal with the NSDateFormatter locale “feature”?
I have run into the same issue. I've raised it as a bug with Apple, and posted it on Open Radar:
http://openradar.appspot.com/9774877
I found this solution :
NSDate *now = [[NSDate alloc] init];
NSTimeZone *localTimeZone = [NSTimeZone systemTimeZone];
NSDateFormatter *rfc3339DateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[rfc3339DateFormatter setLocale:enUSPOSIXLocale];
[rfc3339DateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
[rfc3339DateFormatter setTimeZone:localTimeZone];
NSString *dateString = [rfc3339DateFormatter stringFromDate:now];
NSLog(#"RFC 3339 datetime: %#", dateString);
// 2013-06-27T10:27:08-0600
// 2013-07-22T15:09:30+0100
That fixed 2 of my problems :
When user is setted to 12h display mode, output with this formatter is display as 24h
When you manually set to Dublin timezone, output does not display dateTime with Z but +0000
I had a similar issue, what I ended up doing was to ammend the dateFormat, rather than specifying the timeStyle.
NSDateFormatter *formatter = [[ NSDateFormatter alloc ] init];
if (self.datePickerMode == UIDatePickerModeDateAndTime){
[formatter setDateFormat:[NSString stringWithFormat:#"%# %#", f.dateFormat, #"HH:mm:ss"]];
}
Worked well for me, hope it helps.
Use this format
NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd hh:mm a";
NSString *stringDate = [dateFormatter stringFromDate:[NSDate date]];
Instad of HH (Hour in day (0-23)) use hh (Hour in am/pm (1-12))
Add a (Am/pm marker) in the end of the format.
For example: [NSDate date] is 2017-05-14 12:40:00
In 24-Hour time you will get 2017-05-14 12:40
In 12-Hour time you will get 2017-05-14 12:40 PM
For Today | Yesterday I use NSDateComponents for calculate and return right date.
NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:yourDate toDate:[NSDate date] options:0];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
if (components.year > 0) {
dateFormatter.dateFormat = [NSString stringWithFormat:#"'%#' '%#' MMM d, YYYY", [#"last seen" localized], [#"at" localized]];
}
else if (components.day > 7) {
dateFormatter.dateFormat = [NSString stringWithFormat:#"'%#' MMM d '%#' hh:mm a", [#"last seen" localized], [#"at" localized]];
}
NSString *relativeDateString = [dateFormatter stringFromDate: yourDate];

NSDateFormatter not returning the correct date

I have the following code which is used to take the time of one NSDate and the current date and combine them into one NSDate. However the formatters are set correctly, but it's returning a date that isn't even close to the one it should be. Here is the code
/* Get the current date and make a formatter to just show the date ONLY */
NSDate *currentDate = [NSDate date];
NSDateFormatter *curDateFormatter = [[NSDateFormatter alloc] init];
[curDateFormatter setDateFormat:#"MM/dd/YYYY"];
/* Create a formatter for the time ONLY */
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setDateFormat:#"hh:mm"];
/* Create a formatter for both date and time */
NSDateFormatter *combinedFormatter = [[NSDateFormatter alloc] init];
[combinedFormatter setDateFormat:#"MM/dd/YYYY hh:mm"];
NSString *combinedDateTime = [NSString stringWithFormat:#"%# %#", [curDateFormatter stringFromDate:currentDate], [timeFormatter stringFromDate:time]];
NSDate *combinedDate = [combinedFormatter dateFromString:combinedDateTime];
/* release the formatters */
[curDateFormatter release];
[timeFormatter release];
[combinedFormatter release];
return combinedDate;
Say it is doing it when this message was posted, it should have 11/10/2010 06:47 but instead it's like 12/27/2009 11:45. Does this in the simulator and the device.
Instead of using the combinedDateFormatter, try the following:
NSDate *combinedDate = [NSDate dateWithNaturalLanguageString:combinedDateTime];
This worked fine for me.
Value for combinedDateTime string was 09/27/2011 11:55
Value for combinedDate date object was 2011-09-27 11:55:00 +0530
Take a look at below URL;
Formatting NSDate into particular styles for both year, month, day, and hour, minute, seconds

Retrieving current local time on iPhone?

I'm looking to get the current hour and minute on a user's iPhone for display in an app that doesn't show the status bar. Is there a simple way to do this?
// get current date/time
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
NSString *currentTime = [dateFormatter stringFromDate:today];
[dateFormatter release];
NSLog(#"User's current time in their preference format:%#",currentTime);
-(void)currentTime
{
//Get current time
NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *dateComponents = [gregorian components:(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:now];
NSInteger hour = [dateComponents hour];
NSString *am_OR_pm=#"AM";
if (hour>12)
{
hour=hour%12;
am_OR_pm = #"PM";
}
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];
[gregorian release];
NSLog(#"Current Time %#",[NSString stringWithFormat:#"%02ld:%02ld:%02ld %#", (long)hour, (long)minute, (long)second,am_OR_pm]);
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter stringFromDate:[NSDate date]]
[dateFormatter release]; dateFormatter = nil;
I think you should try this. The timeZone is important.
See this similar question for an answer. You will have to change it to your date format.
[[NSDate date] timeIntervalSince1970];
if you are looking to calculate time intervals, you are better off using CACurrentMediaTime
double currentTime = CACurrentMediaTime();
A shorter approach
NSDate * now = [NSDate date];
timeLabel.text = [NSDateFormatter localizedStringFromDate:now
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterShortStyle];
CFAbsoluteTimeGetCurrent()
Absolute time is measured in seconds relative to the absolute reference date of Jan 1 2001 00:00:00 GMT. A positive value represents a date after the reference date, a negative value represents a date before it. For example, the absolute time -32940326 is equivalent to December 16th, 1999 at 17:54:34. Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.