I am trying to convert following string "2016-05-15T14:40:43.447" to NSDate but its not NSDateFormatter always returns nil.
This is what I'm doing currently.
- (NSTimeInterval) timeIntervalFromDateString:(NSString *)stringDate {
if(!stringDate || ![stringDate length]) {
return 0.0f;
}
static NSDateFormatter *df = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
df = [NSDateFormatter new];
[df setDateFormat:#"yyyy-MM-dd'T'hh:mm:ss.SSS"];
});
NSDate *date = [df dateFromString:stringDate];
// date is always returns nil.
return [date timeIntervalSince1970];
}
I have tried setting following formats:
yyyy-MM-dd'T'hh:mm:ss.SSS
yyyy-MM-dd'T'hh:mm:ssz
yyyy-MM-dd'T'hh:mm:ss Z
yyyy-MM-dd'T'hh:mm:ss.SSS Z
yyyy-MM-dd'T'hh:mm:ss.SSS z
But none of them worked.
I have checked What format string do I use for milliseconds in date strings on iPhone? as well, but doesn't help.
Any luck?
14:40:43 is 24 hour format, that's capital H
yyyy-MM-dd'T'HH:mm:ss.SSS
Try this code
- (NSTimeInterval) timeIntervalFromDateString:(NSString *)stringDate {
if(!stringDate || ![stringDate length]) {
return 0.0f;
}
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.timeZone = [NSTimeZone localTimeZone];
df.dateFormat = #"yyyy-MM-dd'T'HH:mm:ss.SSS";
NSDate *date = [df dateFromString:stringDate];
return [date timeIntervalSince1970];
}
Related
I am trying to figure out the way to check my date time is between two others date time, for example I am getting current time from my server as "Mar 16 2015 14:17" so I want to check that whether this date time is between two others date time range as "Feb 4 2015 08:00-09:00" or not.
I would suggest the following class method
+ (BOOL)checkDate:(NSDate*)dateToCheck startingDate:(NSDate*)startingDate endDate:(NSDate*)endDate
{
BOOL returnValue;
if ([startingDate compare:endDate]==NSOrderedDescending)
{
returnValue = [dateToCheck compare:endDate]==NSOrderedAscending && [dateToCheck compare:startingDate]==NSOrderedDescending;
}
else if ([startingDate compare:endDate]==NSOrderedAscending)
{
returnValue = [dateToCheck compare:startingDate]==NSOrderedAscending && [dateToCheck compare:endDate]==NSOrderedDescending;
}
else
{
returnValue = [dateToCheck compare:startingDate]==NSOrderedSame && [dateToCheck compare:endDate]==NSOrderedSame;
}
return returnValue;
}
Current date :
NSDate *currentDate = [NSDate date];
NSLog(#"-- %#",currentDate);
Start date :
// Start Date - 2015-03-12 00:00:58 +0000
NSString *stringStartDate = #"2015-03-12 00:00:58";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSDate *dateStart = [formatter dateFromString:stringStartDate];
End date :
// End Date - 2015-03-20 00:00:58 +0000
NSString *stringEndDate = #"2015-03-20 00:00:58";
NSDateFormatter *formatter1 = [[NSDateFormatter alloc] init];
[formatter1 setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSDate *dateEnd = [formatter1 dateFromString:stringEndDate];
Function to check date between two date or not
BOOL isDateCheck = [self isDate:currentDate inRangeFirstDate:dateStart lastDate:dateEnd];
Function
- (BOOL)isDate:(NSDate *)date inRangeFirstDate:(NSDate *)firstDate lastDate:(NSDate *)lastDate {
return [date compare:firstDate] == NSOrderedDescending &&
[date compare:lastDate] == NSOrderedAscending;
}
Try that code if you have three NSDate instances:
NSDate *beginDate, *endDate, *checkDate;
if ([beginDate laterDate:checkDate] == checkDate &&
[checkDate laterDate:endDate] == endDate) {
//checkDate in between beginDate and endDate
}
For date parsing use the following:
NSString *inputRange = #"Feb 4 2015 08:00-09:00";
NSRange firstRange = NSMakeRange(0, inputRange.length - 6);
NSString *firstDate = [inputRange substringWithRange:firstRange];
NSDateFormatter *dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = #"MMM dd yyyy HH:mm";
NSDate *beginDate = [dateFormatter dateFromString:firstDate];
NSString *secondDate = [inputRange substringWithRange:NSMakeRange(0, inputRange.length - 11)];
secondDate = [secondDate stringByAppendingString:[inputRange substringWithRange:NSMakeRange(inputRange.length - 5, 5)]];
NSDate *endDate = [dateFormatter dateFromString:secondDate];
It is too much confusing and i have pasted my code below.
I have a eopoc time.
// Function that converts eopc to NSString
NSString * ConvertEpocToDateStr(NSString *epoc)
{
NSString *res;
NSTimeInterval sec = [epoc doubleValue]/1000.0;
NSDate *eDate = [[NSDate alloc] initWithTimeIntervalSince1970:sec];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM/dd hh:mm a"];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"IST"];
NSLog (#" Time in your Zone is %# ", [[dateFormatter timeZone] description]);
res = [dateFormatter stringFromDate:eDate];
return res;
}
// From NSString to back NSDate.
NSDate * backToDate (NSString * dInStr )
{
NSDateFormatter *dFormatter = [[NSDateFormatter alloc] init];
[dFormatter setDateFormat:#"MM/dd hh:mm a"];
dFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"IST"];
NSDate *FromString = [dFormatter dateFromString:dInStr];
return dFromString;
}
And, I tried to print below .
epoc -> 1397600251077
ConvertEpocToDateStr -> 04/16 03:47 am
backToDate -> 2000-04-15 22:17:00 +0000
Both should be same right? I am not sure where/what i am missing?
Of course, you get the same dates. IST is 5.30 h ahead of GMT+0.
Since you drop out year in your direct formatter and use the date time string without the year
by default it is set to 2000.
Evidently, 2000-04-15 22:17:00 +0000 is the same as 2000-04-16 03:47:00 +0530.
I am new to ios development. I am making a custom datepicker using uipickerview. I have datesArray to be used as a data source for uipickerview.
I want to know how to show only Labels : today,tomorrow,Fri,Sat,Sun,Mon,Tues for current week and rest dates in format "EEE, LLL d".
I tried this code but it didn't work.
for(int i=0;i<22;i++)
{
NSDate *myDate = [NSDate dateWithTimeIntervalSinceNow:60 * 60 * 24 * i];
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateFormat:#"EEE, LLL d"];
if(myDate==now)
{
NSString *myDateString=#"today";
[datesArray addObject:myDateString];
}
else
{
NSString *myDateString = [dateFormatter stringFromDate:myDate];
[datesArray addObject:myDateString];
}
}
Try this.Hope it helps
NSString *dateFromWS = #"2013-10-16";//im taking it as static you have to take string coming from webservice
for (int i = 0; i < 22; i++)
{
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter1 setDateFormat:#"yyyy-MM-dd"];
NSDate *myDate = [NSDate dateWithTimeIntervalSinceNow:60 * 60 * 24 * i];
NSDate *now = [dateFormatter1 dateFromString:dateFromWS];
NSDate *tomorrow = [NSDate dateWithTimeInterval:60 * 60 * 24 * 1 sinceDate:now];
//NSDate *dummy = [NSDate dateWithTimeInterval:60 * 60 * 24 * 1 sinceDate:now];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateFormat:#"EEE, LLL d"];
NSString *loopDate = [dateFormatter stringFromDate:myDate];
NSString *today = [dateFormatter stringFromDate:now];
NSString *tomorrowString = [dateFormatter stringFromDate:tomorrow];
if ([loopDate isEqualToString:today]) {
[datesArray addObject:#"today"];
} else if ([loopDate isEqualToString:tomorrowString]) {
[datesArray addObject:#"tomorrow"];
} else if ((i/7) < 1) {
[datesArray addObject:[loopDate substringToIndex:3]];
} else {
[datesArray addObject:loopDate];
}
}
if(myDate==now)
is comparing 2 pointers not 2 dates. You need to use the below code
if([myDate compare:now] == NSOrderedSame)
In addition to Simon's pointer issue, your dates will include the time info and so is never likely to be identical. May be the same day but not the same time. You need to find if the day matches. I do this by:
for(int i=0;i<22;i++)
{
NSDate *myDate = [NSDate dateWithTimeIntervalSinceNow:60 * 60 * 24 * i];
NSDate *myDateNoTime = nil;
// Note: Create sysCal as a property so it is not being repeatedly recreated here
[self.sysCal rangeOfUnit:NSDayCalendarUnit startDate:&myDateNoTime interval:nil forDate:myDate];
NSDate *now=[NSDate date];
NSDate *todayDateNoTime = nil;
[self.sysCal rangeOfUnit:NSDayCalendarUnit startDate:&todayDateNoTime interval:nil forDate:now];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateFormat:#"EEE, LLL d"];
if([myDateNoTime isEqualToDate:todayDateNoTime])
{
NSString *myDateString=#"today";
[datesArray addObject:myDateString];
}
else
{
NSString *myDateString = [dateFormatter stringFromDate:myDate];
[datesArray addObject:myDateString];
}
}
Given your server date requirement and, in my opinion, a better way of handling a picker, I would put this in the datasource method instead.
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *resultString = nil;
NSDate *myDate = [self dateForRow:row];
NSDate *myDateNoTime = nil;
// Note: Create sysCal as a property so it is not being repeatedly recreated here
[self.sysCal rangeOfUnit:NSDayCalendarUnit startDate:&myDateNoTime interval:nil forDate:myDate];
NSDate *now=[NSDate date];
NSDate *todayDateNoTime = nil;
[self.sysCal rangeOfUnit:NSDayCalendarUnit startDate:&todayDateNoTime interval:nil forDate:now];
if([myDateNoTime isEqualToDate:todayDateNoTime])
{
resultString = #"Today";
} else {
// Note: using property for date formatter so I am not repeatedly creating here
resultString = [self.dayFormatter stringFromDate:myDate];
}
return resultString;
}
To determine date for the row use:
-(NSDate *)dateFromRow:(NSInteger)inRow {
NSDateComponents *daysToAdd = [[NSDateComponents alloc] init];
[daysToAdd setCalendar:self.sysCal];
NSInteger daysCalc = (-1 * (inRow -2));
[daysToAdd setDay:daysCalc];
NSDate *resultDate = nil;
NSDate *calcDate = [self.sysCal dateByAddingComponents:daysToAdd
toDate:self.myServerDate
options:0];
[self.sysCal rangeOfUnit:NSDayCalendarUnit startDate:&resultDate interval:nil forDate:calcDate];
return resultDate;
}
I suppose you are already set with the way you are doing it but I think you would find this more flexible, no limit to 21 days before or after the server date. Aircode, excuse any typos or syntax errors.
Swift 4.0
for i in 0..<22 {
var myDate = Date(timeIntervalSinceNow: 60 * 60 * 24 * i)
var now = Date()
var dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.dateFormat = "EEE, LLL d"
if myDate == now {
var myDateString = "today"
datesArray.append(myDateString)
} else {
var myDateString: String = dateFormatter.string(from: myDate)
datesArray.append(myDateString)
}
}
This question already has answers here:
Objective-C String(yyyy-mm-dd) to NSDate
(3 answers)
Closed 9 years ago.
I get null date even when the string that I pass has a date as shown below:-
Generic input Date Format is "MM/dd/YYYY hh:mm a"
NSString input Date can be one of the following: "12/1/2012" , "12/1/2012 01:43 am" , "01:43 am"
Expected output which I am trying is that , it must print date if it exists in input string and time must be printed out if it exists in the input string.
Input:-
[self testDate:#"12/1/2012"]
Code:-
-(void) testDate:(NSString*) str{
NSDateFormatter *formatter=[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM/dd/yyyy hh:mm a"];//My Generic Date Format
self.dateTest=[formatter dateFromString:str];
[self printDate:self.dateTest];
}
-(void) printSeparatedDateAndTime:(NSDate*) date{
NSDateFormatter *dateF=[[NSDateFormatter alloc] init];
[dateF setDateFormat:#"MM/dd/yyyy"];
NSString *dateStr=[dateF stringFromDate:date];
NSLog(#"Date= %#",dateStr);
[dateF setDateFormat:#"hh:mm a"];
NSString *timeStr=[dateF stringFromDate:date];
NSLog(#"Time= %#",timeStr);
}
Output Date:-
Date= (null)
Time= (null)
Input can be in any format, ex
input
"12/1/2012"
output
date="12/1/2012"
time=null
input
"12/1/2012 01:43 am"
output
date="12/1/2012"
time=01:43 am
input
"01:43 am"
output
date=null
time="01:43 am"
One can get a different answer here Objective-C String(yyyy-mm-dd) to NSDate. This refers to answer if date format set is wrong.
In my case date format is correct. But it might have only date, only time or both of them.
To separate date and time from a String one can refer here ios4 - splitting a date and time from a string into two separate strings, but it does not have a checked answer or a valid answer.
Remove hh:mm a and the format can be either "MM/dd/yyyy" or "dd/MM/yyyy".
-(void) testDate:(NSString*) str{
NSDateFormatter *formatter=[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd/MM/yyyy"];
self.dateTest=[formatter dateFromString:str];
[self printDate:date];
}
Your printeDate: will not work as expected since the date created don't have any information about the time and you are trying to show hours and minutes.It will always show 12.00 AM.
If you want to show hours and minutes you need to include that also in your input string.
EDIT : Since dateFormats can be in three formats you need to do a trial and error.
-(void) testDate:(NSString*) str{
NSArray *dateFormats = #[#"dd/MM/yyyy",#"hh:mm a",#"dd/MM/yyyy hh:mm a"];
NSDateFormatter *formatter=[[NSDateFormatter alloc] init];
NSDate *date = nil;
for (NSString *dateFormat in dateFormats) {
[formatter setDateFormat:dateFormat];
date = [formatter dateFromString:str];
if (date) {
break;
}
}
[self printDate:date];
}
OR
-(void) testDate:(NSString*) dateString
{
NSDate *date = nil;
NSError *error = nil;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeDate
error:&error];
NSArray *matches = [detector matchesInString:dateString
options:0
range:NSMakeRange(0, [dateString length])];
for (NSTextCheckingResult *match in matches) {
if (match.date) {
date = match.date;
break;
}
}
[self printDate:date];
}
EDIT 2 : As it is a requirement to have data/time to nil out. Please try
typedef enum {
ValidDateType = 0,
ValidTimeType = 1,
ValidDateTimeType =2
}ValidType;
- (void)testDate:(NSString*) dateString
{
NSArray *dateFormats = #[#"dd/MM/yyyy",#"hh:mm a",#"dd/MM/yyyy hh:mm a"];
NSDateFormatter *formatter=[[NSDateFormatter alloc] init];
__block NSDate *date = nil;
__block ValidType type = ValidDateType;
[dateFormats enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *dateFormat = (NSString *)obj;
[formatter setDateFormat:dateFormat];
date = [formatter dateFromString:dateString];
if (date) {
type = idx;
*stop = TRUE;
}
}];
[self printDate:date validType:type];
}
- (void)printDate:(NSDate*) date validType:(ValidType)type
{
NSDateFormatter *dateF=[[NSDateFormatter alloc] init];
[dateF setDateFormat:#"MM/dd/yyyy"];
NSString *dateStr=[dateF stringFromDate:date];
[dateF setDateFormat:#"hh:mm a"];
NSString *timeStr=[dateF stringFromDate:date];
dateStr = (type == ValidTimeType)?nil:dateStr;
timeStr = (type == ValidDateType)?nil:timeStr;
NSLog(#"Time= %#",timeStr);
NSLog(#"Date= %#",dateStr);
}
You set the date format to include time: MM/dd/yyyy hh:mm a, but you are not passing any time with you string: 12/1/2012.
Just remove the hh:mm a from the date format :
-(void) testDate:(NSString*) str{
NSDateFormatter *formatter=[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM/dd/yyyy"];
self.dateTest = [formatter dateFromString:str];
[self printDate:self.dateTest];
}
Also I would suggest not using a static date format, just incase you have any non America users. Apple has added NSDateFormatterStyle to make it easy for you to use the user/system selected style of formatting.
-(void) printDate:(NSDate*) date{
NSDateFormatter *dateF=[[NSDateFormatter alloc] init];
dateF.dateStyle = NSDateFormatterMediumStyle;
dateF.timeStyle = NSDateFormatterNoStyle;
NSString *dateStr=[dateF stringFromDate:date];
NSLog(#"Date= %#",dateStr);
dateF.dateStyle = NSDateFormatterNoStyle;
dateF.timeStyle = NSDateFormatterShortStyle;
NSString *timeStr=[dateF stringFromDate:date];
NSLog(#"Time= %#",timeStr);
}
I know that the NSDateformatter suite of functionality is a boon for mankind, but at the same time it is very confusing to me. I hope you can help me out.
Somewhere in my code, there is an int representing a month. So: 1 would be January, 2 February, etc.
In my user interface, I would like to display this integer as proper month name. Moreover, it should adhere to the locale of the device.
Thank you for your insights
In the mean time, I have done the following:
int monthNumber = 11
NSString * dateString = [NSString stringWithFormat: #"%d", monthNumber];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
[dateFormatter release];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM"];
NSString *stringFromDate = [formatter stringFromDate:myDate];
[formatter release];
is this the way to do it? It seems a bit wordy.
Another option is to use the monthSymbols method:
int monthNumber = 11; //November
NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease];
NSString *monthName = [[df monthSymbols] objectAtIndex:(monthNumber-1)];
Note that you'll need to subtract 1 from your 1..12 monthNumber since monthSymbols is zero-based.
let monthName = DateFormatter().monthSymbols[monthNumber - 1]
You can change the dateFormat of the NSDateFormatter. So to simplify your code:
int monthNumber = 11
NSString * dateString = [NSString stringWithFormat: #"%d", monthNumber];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
[formatter setDateFormat:#"MMMM"];
NSString *stringFromDate = [formatter stringFromDate:myDate];
[dateFormatter release];
You should also set the locale once you init the date formatter.
dateFormatter.locale = [NSLocale currentLocale]; // Or any other locale
Hope this helps
Best solution for this is , standaloneMonthSymbols method,
-(NSString*)MonthNameString:(int)monthNumber
{
NSDateFormatter *formate = [NSDateFormatter new];
NSArray *monthNames = [formate standaloneMonthSymbols];
NSString *monthName = [monthNames objectAtIndex:(monthNumber - 1)];
return monthName;
}
How about:
NSUInteger i = <your month integer>;
NSDateFormatter *df = [NSDateFormatter new];
// change locale if the standard is not what you want
NSArray *monthNames = [df standaloneMonthSymbols];
NSString *monthName = [monthNames objectAtIndex:(i - 1)];
[df release];
Both answers from Anna Karenina and Carl doesn't work that well as they won't return month name in nominativ for some cultures. I suggest to use the proposed solution from Pascal, which solves this issue (by replacing monthSymbols with standaloneMonthSymbols)
In Swift 3.0
let monthNumber = 3
let fmt = DateFormatter()
fmt.dateFormat = "MM"
let month = fmt.monthSymbols[monthNumber - 1]
print(month)
// result
"March\n"
Swift 4.X
print((DateFormatter().monthSymbols[month-1].capitalized)) //month is int less than 12
For Example:
print((DateFormatter().monthSymbols[11-1].capitalized))
Output
November
NSDate to NSString -> As Dateformat Ex: 2015/06/24
NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
[dateformate setDateFormat: #"yyyy/MM/dd"];
NSString *date = [dateformate stringFromDate:selectedDate]; // Convert date to string
NSDate to NSString -> As Dateformat Ex: 2015 June 24, 1:02 PM
[dateformate setDateFormat:#"yyyy MMMM dd, h:mm a"];
NSString *displayDate = [dateformate stringFromDate:selectedDate]; // Convert date to string
NSLog(#"date :%#",date);
NSLog(#"Display time = %#", displayDate);
And with ARC :
+ (NSString *)monthNameFromDate:(NSDate *)date {
if (!date) return #"n/a";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MM"];
return [[df monthSymbols] objectAtIndex:([[df stringFromDate:date] integerValue] - 1)];
}
You should be able to get rid of the release and re-allocation of the dateFormatter, cutting out a couple of lines, but that's all I see.