If I send the method dateByAddingTimeInterval: to NSDate, like below:
NSDate *today = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0];
NSDate *yesterday = [now dateByAddingTimeInterval:-24.0];
NSArray *dates = [NSArray arrayWithObjects: today, tomorrow, yesterday, nil];
NSLog(#"today's date is %#", [dates objectAtIndex:0]);
NSLog(#"yesterday's date was %#", [dates objectAtIndex:2]);
I get this output:
...The first date is 2012-08-30 02:14:19 +0000
...The third date is 2012-08-30 02:13:55 +0000
Which is strange because the third date should have been 2012-08-29
But... if I change the NSDate messages to:
NSDate *today = [NSDate date];
NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0];
NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0];
Why does adding the * 60.0...
...The first date is 2012-08-30 02:15:25 +0000
...The third date is 2012-08-29 02:15:25 +0000
make the output correct?
Thank you.
NSDate compute time by second.
Related
I have the date string "2016-04-01T05:00:00+08:00" and I want to convert it into number of seconds since 1 January 1970. I am doing like this:
NSDateFormatter *parsingFormatter = [NSDateFormatter new];
[parsingFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
NSDate *date = [parsingFormatter dateFromString:"2016-04-01T05:00:00+08:00"];
NSTimeInterval startTime = [date timeIntervalSince1970];
But in the above example startTime returns nil. Can someone tell me what I am doing wrong? How can I convert it?
Try this
NSDateFormatter *parsingFormatter = [NSDateFormatter new];
[parsingFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZZZ"];
NSDate *date = [parsingFormatter dateFromString:#"2016-04-01T05:00:00+08:00"];
NSTimeInterval startTime = [date timeIntervalSince1970];
I am getting date "2016-03-31 21:00:00 +0000" UTC format.
Im here in the UK and when working with dates in iOS they are always out by one hour (one hour behind), what I need is the correct time from an NSDate. Ive done the following, but i get two different times:
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSLog(#"NSDate %#",today);
NSLog(#"Time %#", [dateFormatter stringFromDate:today]);
NSDate*stringDate = [dateFormatter dateFromString:[dateFormatter stringFromDate:today]];
NSLog(#"Time date %#",stringDate);
Here is what is logged:
NSDate 2015-07-01 16:07:22 +0000
Time 2015-07-01 17:07:22
Time date 2015-07-01 16:07:22 +0000
Why is this happening? Am i missing something obvious? Surely if the string date is correct, then doing dateFromString should yield the correct results?
The reason I need an NSDate is so I can get the correct amount of seconds using [myTime timeIntervalSince1970]
2015-07-01 17:07:22 //is the correct date
Im expecting an NSDate object that is correct to my date and time.
Update
The answers below helped me find where I was going wrong, so I changed my approach, I was able to get the current timestamp doing the following:
NSString *timeStamp = [dateFormatter stringFromDate:[NSDate date]];
NSDate *curdate = [dateFormatter dateFromString:timeStamp];
int unix_timestamp = [curdate timeIntervalSince1970];
NSDate* referenceDate = [NSDate dateWithTimeIntervalSince1970: 0];
NSTimeZone* timeZone = [NSTimeZone systemTimeZone];
int offset = (int)[timeZone secondsFromGMTForDate: referenceDate];
int currentTimestamp = unix_timestamp + offset;
NSLog(#"CUrrent time stamp %d",currentTimestamp);
NSDate is an absolute moment of time, it does not have a timezone. The date object you have is correct: it is exactly the moment that code was executed.
If you need string representation of that moment of time in a specific time zone, use stringFromDate: just like you did.
If you need to know number values of hour/minute in a specific time zone, use -[NSCalendar components:fromDate:].
[calendar setTimeZone:...];
NSDateComponents* components = [calendar components:(NSHourCalendarUnit|NSMinuteCalendarUnit) fromDate:date];
The date formatter defaults to the local timezone. If you want a different timezone specify it. NSLog of a date used the 'NSDatedescription` method that defaults to GMT (UTC).
Examining the code:
NSDate *today = [NSDate date];
// Creates today's data in GMT (UTC) All NSDates are referenced to GMT.
NSLog(#"NSDate %#",today); (moved up for explanation ordering)
// NSDate 2015-07-01 16:07:22 +0000
// Displays the date in GMT
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
// Creates a date for matter with the system timezone
NSLog(#"Time %#", [dateFormatter stringFromDate:today]);
// Time 2015-07-01 17:07:22
// Creates a string representation in the system timezone and displays it
NSDate*stringDate = [dateFormatter dateFromString:[dateFormatter stringFromDate:today]];
// Creates a date from the string taking into the system timezone
NSLog(#"Time date %#",stringDate);
// Time date 2015-07-01 16:07:22 +0000
// Displays the date in GMT.
I am trying to convert a mysql datetime field to another timezone. The conversion seems correct when I print the date object, however when I print the date as a string the time is incorrect. Source code and output are below.
Source:
edited - print original interval in seconds and string, add timezones
interval = [NSNumber numberWithDouble: seconds];
NSLog(#"interval in ms: %#",interval);
self.dateStamp = [[NSDate alloc] initWithTimeIntervalSince1970:seconds/1000];
if(![currentZone.name isEqualToString: timezone]){ //need to convert
NSDateFormatter *fromTZ = [[NSDateFormatter alloc]init];
[fromTZ setTimeZone:currentZone];
[fromTZ setDateFormat:#"hh:mm yyyy-MM-dd"];
NSLog(#"original date: %#",[fromTZ stringFromDate:self.dateStamp]);
NSDateFormatter *toTZ = [[NSDateFormatter alloc]init];
[toTZ setTimeZone:spotZone];
[toTZ setDateFormat:#"hh:mm yyyy-MM-dd"];
NSString *tempdate = [fromTZ stringFromDate:self.dateStamp];
NSDate *toDate = [toTZ dateFromString:tempdate];
NSLog(#"Date: %#",toDate);
NSLog(#"Date String: %#", [toTZ stringFromDate:toDate]);
}
Output:
interval in ms: 1384193573000
original date: 01:12 2013-11-11 //date in current timezone: America/Phoenix
Date: 2013-11-11 08:12:00 +0000 //date in new timezone: America/New York
Date String: 01:12 2013-11-11
NSDate has no concept of time zone, it is simply an object representing the number of seconds since January 1, 2001 GMT and represented in UTC. No matter what you try and set it to, when you straight log an NSDate its going to give you the same result. The only way to circumvent this is to use the NSDateFormatter which you've already done. Everything you've posted is the expected behavior.
Your server sends the time 1384193573000 (in milliseconds) since 1.1.1970, but not with respect to GMT as it is usually done, but with respect to a different time zone, "America/Phoenix" in your example.
Therefore you have to add a correction first, which is the difference between "America/Phoenix" and GMT:
NSTimeInterval serverTime = 1384193573000/1000.;
NSTimeZone *fromZone = [NSTimeZone timeZoneWithName:#"America/Phoenix"];
NSTimeInterval diff = [fromZone secondsFromGMTForDate:[NSDate dateWithTimeIntervalSince1970:0]];
NSDate *dateStamp = [NSDate dateWithTimeIntervalSince1970:(serverTime - diff)];
This was the crucial step. dateStamp is now a "proper" NSDate object representing
the time sent from the server.
What remains is to display the date. That is done as in the above comments and the other
answer. For example:
NSTimeZone *toZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
NSDateFormatter *toTZ = [[NSDateFormatter alloc]init];
[toTZ setTimeZone:toZone];
[toTZ setDateFormat:#"HH:mm yyyy-MM-dd"];
NSString *result = [toTZ stringFromDate:dateStamp];
// result = 20:12 2013-11-11
I found the codes to calculate days difference between two dates here.
I write a method :
-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSInteger startDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:startDate];
NSInteger endDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:endDate];
return endDay-startDay;
}
This method has a problem: it can't consider the timezone thing. Even I add a line like this:
[gregorian setTimeZone:[NSTimeZone localTimeZone]];
My test code is like this:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *strDate = #"2012-09-03 23:00:00";
NSDate *dateStart = [dateFormat dateFromString:strDate];
strDate = #"2012-09-04 01:00:00";
NSDate *dateEnd = [dateFormat dateFromString:strDate];
NSLog(#"Days difference between %# and %# is: %d days",[dateFormat stringFromDate:dateStart],[dateFormat stringFromDate:dateEnd],[self daysWithinEraFromDate:dateStart toDate:dateEnd]);
The result is:
Days difference between 2012-09-03 23:00:00 and 2012-09-04 01:00:00 is: 0 days
I want to get 1 day as result by the number of midnights between the two dates. My timezone is GMT +8. But this calculation is based on GMT, so I get the wrong days number. Is there anyway to solve this problem? Thank you.
Scott Lemmon's method can solve my problem. I rewrite my code like this:
-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setTimeZone:[NSTimeZone localTimeZone]];
NSDate *newDate1 = [startDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
NSDate *newDate2 = [endDate dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
NSInteger startDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:newDate1];
NSInteger endDay=[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:newDate2];
return endDay-startDay;
}
If the time zone offset isn't working, how about just add or subtract it manually instead?
In your case NSDate *newDate = [oldDate dateByAddingTimeInterval:(-8 * 60 * 60)]; to subtract off your +8 hours.
Or if you want to find the GMT offset automatically as well then it would simply be NSDate *newDate = [oldDate dateByAddingTimeInterval:(-[[NSTimeZone localTimeZone] secondsFromGMT])
Another thought:
A perhaps easier solution would be to just disregard the time information altogether. Just set it to the same arbitrary number for both dates, then as long as the dates come from the same timezone you will always get the correct number of mid-nights between them, regardless of GMT offset.
What you really want is the NSDate method timeIntervalSinceDate:, and take that result and if it's more than 0 but less than 86400 (the number of seconds in a day), that's one day. Otherwise, divide your result by 86400 and you'll get the number of days.
The way you currently have your code, there's only 2 hours between the two days and that's why you are seeing a result of 0 and not one.
Edit - and to determine if midnight has happened, let's try this function I just wrote off the top of my head:
- (NSDate *) getMidnightDateFromDate: (NSDate *) originalDate
{
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSIntegerMax fromDate:originalDate];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSDate *midnight = [[NSCalendar currentCalendar] dateFromComponents:components];
return(midnight);
}
- (BOOL) howManyDaysDifferenceBetween: startDate and: endDate
{
NSDate * firstMidnight = [self getMidnightDateFromDate: startDate];
NSDate * secondMidnight = [self getMidnightDateFromDate: endDate];
NSTimeInterval timeBetween = [firstMidnight timeIntervalSinceDate: secondMidnight];
NSInteger numberOfDays = (timeBetween / 86400);
return(numberOfDays);
}
which I'm basing off Dave Delong's answer to this question. No guarantees that my code will work (I didn't test it), but I think the concept is sound.
I am displaying time. It will show me :TIME :2012-06-18 23:00:00 +0000
But after using NSDateFormatter I do not know why it is giving me 00:00:00 AM
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss a"];
NSLog(#"TIME :%#",self.startDate);
NSDate *date = [NSDate date];
NSString * _startTime = [dateFormatter stringFromDate:date];
NSLog(#"current time : %#",_startTime);
NSString * _startTime1 = [dateFormatter stringFromDate:self.startDate];
NSLog(#"Start time : %#",_startTime1);
[dateFormatter release];
**Result is**
TIME :2012-06-18 23:00:00 +0000
current time : 17:05:41 PM
Start time : 00:00:00 AM
Your first NSLog outputs the date in GMT time (notice the trailing +0000). An NSDateFormatter object will format the date to the specified time zone. Your NSLog statements show that the stored date in self.startDate is exactly 00:00:00 AM in at least one time zone, and the formatter is set to that time zone. The formatter will default to the time zone for the device. You could set the formatter's timezone to 0 seconds from GMT to see 23:00:00 PM out of your last NSLog statement:
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];