I'm using the following date formatter:
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mm a" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
return _dateFormatter;
}
An output example could be:
Mar 25, 2:05 PM
I need to change 1 thing:
no space between the hour and the am/pm
like this:
Mar 25, 2:05PM
Try this solution, it worked for me. (simply remove the space between mm and a)
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mma" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
return _dateFormatter;
}
I was using DateFormatter.dateFormat(fromTemplate: "h:mma", options: 0, locale: Locale.current)!, but that consistently added a space before my am/pm marker. Setting the dateFormat property directly with a string worked.
let formatter = DateFormatter()
formatter.amSymbol = "a"
formatter.pmSymbol = "p"
formatter.dateFormat = "h:mma"
let timeLabel = formatter.string(from: Date())
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:#"MMM d, h:mmaaa"];
});
return _dateFormatter;
}
how about not to use template?
template's am/pm can't be sticked with minutes, weird
Can you try like this
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mm a" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
NSString *date = [_dateFormatter stringFromDate:[NSDate date]];
NSArray *aa = [date componentsSeparatedByString:#" "];
NSString *combinedString = [date stringByReplacingOccurrencesOfString:[NSString stringWithFormat:#" %#",[aa lastObject]] withString:[aa lastObject]];
NSLog(#"date : %#",combinedString);
I create a simple yet not necessary the best solution. So I used my string to present it in a UILabel. So I sublclassed UILabel called ClockLabel and override setter for label's text. Here is the code:
- (void)setText:(NSString *)text {
text = [text stringByReplacingOccurrencesOfString:#" am" withString:#"am"];
text = [text stringByReplacingOccurrencesOfString:#" pm" withString:#"pm"];
[super setText:text];
}
There must be some other soluton but I sticked to this one.
Related
I have 4 UITextfileds, start date, start time and end date, end time. Then I'm sending my date and time into my UTC function, but it's returning null.
NSString *str1 = _startDateField.text;
str1 = [str1 stringByAppendingString:#" "];
str1 = [str1 stringByAppendingString:_startTimeField.text];
NSLog(#"str1 : %#", str1);
NSString *str2 = _endDateField.text;
str2 = [str2 stringByAppendingString:#" "];
str2 = [str2 stringByAppendingString:_endTimeField.text];
NSLog(#"str2 : %#", str2);
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSDate *date1 = [dateFormat dateFromString:str1];
NSDate *date2 = [dateFormat dateFromString:str2];
NSLog(#"%#", date1);
NSLog(#"%#", date2);
NSString *startTime = [self getUTCFormateDate:date1];
NSString *endTime = [self getUTCFormateDate:date2];
NSLog(#"str1 : %#", startTime);
NSLog(#"str2 : %#", endTime);
Coverting to UTC format:
-(NSString *)getUTCFormateDate:(NSDate *)localDate {
NSLog(#"%#", localDate);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSString *dateString = [dateFormatter stringFromDate:localDate];
NSLog(#"%#", dateString);
return dateString;
}
I want to read the date and time from my text fields and convert them into UTC format.
your code is fine and correct, I added the defaultTimeZone for get the time zone and subtract the time to utc time. I got the output.
check this
NSString *str1 = #"26-Nov-2019";
str1 = [str1 stringByAppendingString:#" "];
str1 = [str1 stringByAppendingString:#"9:35 am"];
NSLog(#"str1 : %#", str1);
NSString *str2 = #"26-Nov-2019";
str2 = [str2 stringByAppendingString:#" "];
str2 = [str2 stringByAppendingString:#"11:59"];
NSLog(#"str2 : %#", str2);
// Convert string to date object
NSDate *date1 = [self getUTCDate:str1];
NSDate *date2 = [self getUTCDate:str2];
NSLog(#"date1 %#", date1);
NSLog(#"date2 %#", date2);
NSString *startTime = [self getUTCFormateDate:date1];
NSString *endTime = [self getUTCFormateDate:date2];
NSLog(#"str1 : %#", startTime);
NSLog(#"str2 : %#", endTime);
-(NSDate *)getUTCDate:(NSString *)currentDate {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSDate *date1 = [dateFormat dateFromString:currentDate];
if (date1 == nil) {
[dateFormat setDateFormat:#"dd-MMM-yyyy hh:mm a"];
date1 = [dateFormat dateFromString:currentDate];
}
return date1;
}
-(NSString *)getUTCFormateDate:(NSDate *)localDate {
NSLog(#"%#", localDate);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSLocale *twelveHourLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
dateFormatter.locale = twelveHourLocale;
NSTimeInterval timeZoneoffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSTimeInterval utcTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneoffset;
NSDate *utcCurrentDate = [NSDate dateWithTimeIntervalSinceReferenceDate:utcTimeInterval];
NSString *dateString = [dateFormatter stringFromDate:utcCurrentDate];
NSLog(#"dateString %#", dateString);
return dateString;
}
I want to connect and pass the action from ViewController to NSObject class file. In my viewcontroller, there is UISwitch Button and if I switch I want to work it in NSObject class file.
When switch is ON from viewcontroller (UIView) then the action have to work in NSObject class file.
I'm coding with Objective-C.
Here is my ViewController.m and I did this in only ViewController file. Not connected to NSOBject class file.
- (void)viewDidLoad{
[super viewDidLoad];
//UISwitch work at viewDidload
[self.mySwitch addTarget:self
action:#selector(stateChanged:) forControlEvents:UIControlEventValueChanged]; }
- (void)stateChanged:(UISwitch *)switchState{
NSLog(#"current calendar: %#", [[NSCalendar currentCalendar] calendarIdentifier]);
//get the date today
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setCalendar:[NSCalendar currentCalendar]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
NSLog(#"Today Date is: %#", [NSDate date]);
self.myLabel.text=dateToday;
if ([switchState isOn]) {
//[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US#calendar=japanese"]];
[formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierJapanese]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
UILabel *dtDate = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 20.0f)];
[dtDate setText:dateToday];
self.myLabel.text =dateToday;
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(#"current date is: %#", dateToday);
NSLog(#"current locale: %#", locale);
} else {
//[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[formatter setCalendar:[NSCalendar autoupdatingCurrentCalendar]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 20.0f)];
[myLabel setText:dateToday];
self.myLabel.text =dateToday;
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// [formatter setDateStyle:NSDateFormatterMediumStyle];
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(#"current locale: %#", locale);
NSLog(#"%#", [formatter stringFromDate: [NSDate date]]);
}
}
If you need just an action then use class methods else create a global variable or a notification observer in NSObject extended class when you get call back from the switch.
- (void)callback:(id)sender
{
[MyObject switchState:sender.state];
}
Currently I have two NSDateFormatters in my app and I want to somehow "combine" them so I only have, since they're parsing the same date.
I have a NSObject called UpcomingReleases, thats where all my JSON info gets stored.
UpcomingRelease.h
- (NSString *) formattedDate;
UpcomingRelease.m
- (NSString *) formattedDate {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:self.release_date];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
My UICollectionViewController (UpcomingReleasesViewController.m)
if([upcomingReleaseDictionary objectForKey:#"release_date"] != NULL)
{
NSString *readableDate = [upcomingReleaseDictionary objectForKey:#"release_date"];
UpcomingRelease *upcoming = [[UpcomingRelease alloc] init];
upcoming.release_date = readableDate;
cell.release_date.text = [NSString stringWithFormat:#"%#", upcoming.formattedDate];
}
My detailedViewController (ReleaseViewController.m)
(_singleRelease is a NSDictionary)
- (void)viewDidLoad
{
[super viewDidLoad];
if([_singleRelease objectForKey:#"release_date"] != NULL)
{
NSString *readableDate = [_singleRelease objectForKey:#"release_date"];
UpcomingRelease *singleRelease = [[UpcomingRelease alloc] init];
singleRelease.release_date = readableDate;
self.release_date.text = [NSString stringWithFormat:#"%#", singleRelease.formattedDate];
}
}
This was working fine, until I added a share on twitter action and I had to add another NSDateFormatter so it could show the readable date inside the tweet (I would get an error saying "No visible interface for ReleaseViewController declares the selected 'formattedDate'" otherwise).
- (NSString *) formattedDate:(NSString *)jsonDateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:jsonDateString];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
#pragma mark - Share on twitter
- (IBAction)shareOnTwitter:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
NSString *formattedDate = [self formattedDate:[_singleRelease objectForKey:#"release_date"]];
[tweetSheet setInitialText:[NSString stringWithFormat:#"%#", formattedDate]];
[self presentViewController:tweetSheet animated:YES completion:nil];
}
}
How can I combine both these NSDateFormatters into one? They're both parsing the same string in the same way (also if there's a better way to show the formattedDate string than the one I'm currently doing would be great).
This is how my JSON shows the date string:
release_date: "2013-11-16T00:00:00.000Z"
Thanks.
As #Hot Licks says:
Make the date formatter a class method:
+ (NSString *) formattedDate:(NSString *)jsonDateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:jsonDateString];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
Put it in a utility class and use it in both cases. In the first case just pass in self.release_date.
-(NSString*) convertToDateString:(NSString*)str{
static NSDateFormatter *InDateFormatter = nil;
static NSDateFormatter *OutDateFormatter = nil;
NSString *outDate = nil;
if([str isKindOfClass:[NSString class]] && [str length] > 0){
NSString *dateStr = [[NSString alloc] initWithString:str];
if (InDateFormatter == nil) {
InDateFormatter = [[NSDateFormatter alloc] init];
InDateFormatter.dateFormat = #"yyyy-MM-dd";
}
if (OutDateFormatter == nil) {
OutDateFormatter = [[NSDateFormatter alloc] init];
OutDateFormatter.dateFormat = #"MM/dd/yy";
}
NSRange rangeOfDash = [dateStr rangeOfString:#"T"];
dateStr = (rangeOfDash.location != NSNotFound) ? [dateStr substringToIndex:rangeOfDash.location] : dateStr;
if([dateStr isKindOfClass:[NSString class]] && [dateStr length] == 10){
NSDate* date = [InDateFormatter dateFromString:dateStr];
if (date != nil) {
outDate = [OutDateFormatter stringFromDate:date];
}
}
}
return outDate;
}
Crash occurred in the line "InDateFormatter.dateFormat = #"yyyy-MM-dd";
There will be multiple instances of class that gets created in parallel and invokes the above method. Crash is rarely reproducible.
Am I not using the date formatter correctly? Thanks in advance
For a thread-safe lazy initialization, you can use the GCD dispatch_once()
function:
static NSDateFormatter *inDateFormatter;
static NSDateFormatter *outDateFormatter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
inDateFormatter = [[NSDateFormatter alloc] init];
inDateFormatter.dateFormat = #"yyyy-MM-dd";
outDateFormatter = [[NSDateFormatter alloc] init];
outDateFormatter.dateFormat = #"MM/dd/yy";
});
I need to sort an NSArray containing time NSString's such as,
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
What I need is to sort the array in ascending order of time.
Is there any way to do such a thing?
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSArray *sortedTimes = [times sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2)
{
NSDate *date1 = [dateFormatter dateFromString:obj1];
NSDate *date2 = [dateFormatter dateFromString:obj2];
return [date1 compare:date2];
}];
optimized version:
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSMutableArray *dates = [NSMutableArray arrayWithCapacity:times.count];
for (NSString *timeString in times)
{
NSDate *date = [dateFormatter dateFromString:timeString];
[dates addObject:date];
}
[dates sortUsingSelector:#selector(compare:)];
NSMutableArray *sortedTimes = [NSMutableArray arrayWithCapacity:dates.count];
for (NSDate *date in dates)
{
NSString *timeString = [dateFormatter stringFromDate:date];
[sortedTimes addObject:timeString];
}
You can try this code:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm a"];
[times sortUsingComparator:^NSComparisonResult(NSString* obj1, NSString *obj2) {
NSDate *firstDate = [formatter dateFromString:obj1];
NSDate *secondDate = [formatter dateFromString:obj2];
return [firstDate compare:secondDate];
}];
As these are strings it will be sored as
01:15, 12:25, 05:00....
And they are not either NSDate.
So you need to do is that Create a parallel array having NSDate from these strings, sort the array, and extract these values.
While implementing I solved it by novice-way
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSMutableArray *dates=[NSMutableArray new];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"hh:mm a"];
for (NSString *stringDate in times) {
NSDate *date=[dateFormatter dateFromString:stringDate];
[dates addObject:date];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [dates sortedArrayUsingDescriptors:descriptors];
[times removeAllObjects];
for (NSDate *date in reverseOrder) {
NSString *string=[dateFormatter stringFromDate:date];
[times addObject:string];
}
NSLog(#"%#",times);
For NSDate Comparison use this:
+ (BOOL)isDate:(NSDate *)date1 smallerThanAnotherDate:(NSDate *)date2
{
NSDate* enddate = date1;
NSDate* currentdate = date2;
NSTimeInterval distanceBetweenDates = [enddate timeIntervalSinceDate:currentdate];
double secondsInMinute = 60;
NSInteger secondsBetweenDates = distanceBetweenDates / secondsInMinute;
if (secondsBetweenDates <= 0)
return YES;
else
return NO;
}
So If you do not want to convert your hours to NSDate do this alone it works for me
NSArray *sortedTimes = [times sortedArrayUsingSelector:#selector(localizedStandardCompare:)];