How to Format NSDate in the Model Layer - core-data

I have a NSDate that I want to return as formatted like 10:00PM.
I have the date formatter working.
I'm wondering how I can make it so that whenever I fetch that date it comes back formatted as desired.
The NSDate in question in a daily start time for an activity that is store in an NSManagedObject
subclass.
#implementation Schedule
#dynamic repeat;
#dynamic start;
-(NSString*)amPMFormat
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"h:mm a"];
return [dateFormatter stringFromDate:self.start];
}
#end
I'm using a keypath to fill in a TableViewCell. The object bound to the cell is a Ritual which knows a Schedule. My thought was to call the method amPMFormat using the keypath and just return the formatted date as a string but that doesn't work. This code is a cell created using Sensible TableView. The cell has a STEP bound to it, STEP has a SCHEDULE, and SCHEDULE has a start property which is an NSDate that only has hours and minutes saved into it.
SCCustomCell *descrCell = [SCCustomCell cellWithText:nil objectBindingsString:#"1:schedule.start.amPMFormat;3:desc" nibName:#"RitualCell"];

You've munged the Model and the View parts of your program.
The date (self.start) is an instant in time. You can represent that date in any of a multitude of calendars, languages, locale-specific formats, and precision. It's still a single instant in time.
The formatter is a way to build a standard string representation of that instant. If you want the date formatted a particular way "whenever [you] fetch that date", you can use -awakeFromFetch: to populate a read-only property. Or perhaps a class method on Schedule, +formattedStringForDate:, which formats an NSDate appropriately and returns an NSString.
Your cryptic second snippet mentions "bindings". Are you using Cocoa Bindings and writing an OS X app? If so, you can put a date formatter on the NSTextField instance in your XIB.

Related

Need to write a predicate to search for a date in a core data object's array property (in my case array of dates)

I need to fetch an object using Core Data. The object has a property datesArray(Array of NSDate objects stored as NSData) which I use to store array of dates. I need to check if the array contains todays date and then use the object.
NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:#"MyEntity"];
NSError * error;
NSArray * fetchedArray = [context executeFetchRequest:request error:&error];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"entity.datesArray CONTAINS %#",[NSDate date]];
for (MyEntity * entity in fetchedArray) {
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:entity.datesArray];
[array filterUsingPredicate:predicate];
if (array.count >0) {
[_myMutableArray addObject:entity];
}
}
You really should not be storing dates like this. You are losing the value of using Core Data. If you have an array of something then that should be on the other side of a relationship which you can then retrieve efficiently from the underlying persistent store.
I suspect that your predicate lacks precision as a date object is down to the nanosecond. If you are looking to match something from "today" then you need to work on something with less precision. Perhaps a string in a specific format or store it as a number and then search within a range (less than X and greater than Y type of search).
Again, storing the actual dates in managed objects makes this question much easier but you are still going to be dealing with a precision problem.

NSFetchedResultsController update every minute with observable NSDate of today?

I have a list of results showing on the UI for the current NSDate. Every minute, I need this list and another field to update (although a change may not occur every minute).
I am using an NSFetchedResultsController with an NSPredicate and a static variable holding the NSDate at the time.
Now I could simply reset the NSFetchedResultsController every minute, but with an observable coredata set that seems a little crude.
Is there a way to make that NSDate variable observable, such that coredata will reevaluate the NSPredicate when it's updated?
var today: NSDate = NSDate()
predicate: NSPredicate(format: "startTime > %# AND endTime < %#" /* AND classCodeNumber != nil" */, today.startOfDay(), today.endOfDay())!...
With passing time, this predicate should change the set of data shown.

NSPredicate without consider time component

From my table I want select all rows of a particular date without considering the time component of NSDate.Please any one suggest a NSPredicate to achieve this ?
NSDate describes an absolute point in time and does not have "day" or "time" components.
The same is true for a Core Data "Date" attribute, which is stored as the number of seconds
since 1 January 2001, GMT in the database.
What you probably want is to fetch all objects where some "Date" attribute falls into the
interval given by the start of a given day and the start of the next day.
Therefore you have to compute these dates first, using NSCalendar methods:
NSDate *yourDate = ...;
NSDate *startOfDay, *startOfNextDay;
NSTimeInterval lengthOfDay;
NSCalendar *cal = [NSCalendar currentCalendar];
[cal rangeOfUnit:NSDayCalendarUnit startDate:&startOfDay interval:&lengthOfDay forDate:yourDate];
startOfNextDay = [startOfDay dateByAddingTimeInterval:lengthOfDay];
Then use a predicate that fetches all objects where the attribute falls between
these two values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"date >= %# AND date < %#",
startOfDay, startOfNextDay];

NSDate value not accessible across methods

Am sorry to ask such a trivial question. Am a newbie to Objective-C, & simply cannot see how to get this working, after having tried several possible ways & google'd around for it. Please help!
My question is simple. I have a class-level NSDate object, which is declared outside any method in the class as:
NSDate *fromDate;
Now, within a method, am setting this value to the date from a DatePicker as:
fromDate = [datePicker date];
Soon after the above assignment, I print its value into the log & it works fine.
NSLog(#"From Date: %#", fromDate);
Now, when I use NSDate's value in another/different method, the value's gone! Why is it not persisted across methods in the same class itself? What can I do for the value to be accessible across methods?
Thanks for your reply.
Hi Remy,
I didn't know Objective-C didn't have class-level variables! Thanks for pointing it out!
Yes, I've set the project (in Xcode) to do ARC (so, I believe that should take care).
Here is the code:
In ViewController.h
....
....
#property (nonatomic, retain) NSDate *historyFromDate;
#property (nonatomic, retain) NSDate *historyToDate;
....
....
-(IBAction) fromDateChosen: (id)sender;
-(void) fetchTheHistory;
In ViewController.m
...
...
#synthesize historyFromDate;
#synthesize historyToDate;
....
....
-(IBAction) fromDateChosen: (id)sender {
NSString *buttonTitle = #"I've chosen the 'FROM' date";
if ([[buttonDateChosen currentTitle] isEqualToString:buttonTitle]) {
NSLog(#"User has chosen the 'From' date");
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
// Get the chosen date value
NSDate *fromDate = [datePicker date];
historyFromDate = fromDate;
// Set the 'to' date label to reflect the user's choice
labelFromDate.text = [dateFormatter stringFromDate:historyFromDate];
NSLog(#"'From' Date Chosen:%#", historyFromDate);
//[dateFormatter stringFromDate:[datePicker date]]);
[self fetchTheMoodHistory];
}
}
...
...
...
-(void) fetchTheHistory {
NSLog(#"Calling fetchTheHistory for the period from %#", historyFromDate);
...
...
}
...
...
fromDateChosen gets called after the user chooses a date form a Date Picker object in the UI.
Within the method 'fromDateChosen', when I print the historyFromDate, the value is correct.
But, when I print it in fetchTheHistory method, the value shows the current date/time (not the one the user chose).
The date property of UIDatePicker is retained by that class, and will be accessible as long as the date picker itself is in scope and valid (not been released). You are storing this date value in a variable, but not retaining it yourself, so when the date picker goes out of scope you lose the value. As a quick fix, do this instead;
fromDate = [[datePicker date] retain];
Now, this is not the best approach, you really should be making the date a property of whatever class is using this information.
Try put the fromDate variable under class scope, e.g:
#implementation ViewController
{
NSDate *fromDate;
}

Get Date Parts from a NSDate value

I'm using a UIDatePicker and I'm having problems with converting this data to a System.DateTime value in MonoTouch. There are problems with conversions from NSDate to DateTime, which I've mostly solved, but now I see that if you choose a date that is NOT in the same Daylight Savings Time period then you are an hour off. For example, if I pick a date in January 2010 I'll have an offset issue.
What I'd like to do is when a user selects a date/time from the UIDatePicker is to get the Year, Month, Day, Hour, and Minute values of the NSDate and just create a New System.DateTime with those values and I'll always be assured to get a date value exactly as the user see's it in the UIDatePicker.
How can I break down a NSDate value into the various date parts?
Thank you.
An easy way to get rid of the daylight saving time problems is to set the time zone to GMT. Then the UIDatePicker will ignore daylight saving time:
_datePicker.TimeZone = NSTimeZone.FromAbbreviation("GMT");
Implicit conversion of NSDate to and from DateTime is quite good in Monotouch, but you must be aware that NSDate is always an UTC time and DateTime is default set to DateTimeKind.Unspecified (when read from database) or DateTimeKind.Locale (when set with DateTime.Today).
The best way to convert without complicated time-zone computations is to force the right DateTimeKind:
// Set date to the date picker (_date is a DateTime with time part 0:00:00):
_datePicker.Date = DateTime.SpecifyKind(_date, DateTimeKind.Utc);
// Get the date from the date picker:
_date = DateTime.SpecifyKind(_datePicker.Date, DateTimeKind.Unspecified);
This is easier and more reliable than getting the individual Day, Month and Year values.
It appears this can be done using an instance of NSDateComponents. The following has been copied from Date Components and Calendar Units:
To decompose a date into constituent
components, you use the NSCalendar
method components:fromDate:. In
addition to the date itself, you need
to specify the components to be
returned in the NSDateComponents
object. For this, the method takes a
bit mask composed of Calendar Units
constants. There is no need to specify
any more components than those in
which you are interested. Listing 3
shows how to calculate today’s day and
weekday.
Listing 3 Getting a date’s components
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:today];
NSInteger day = [weekdayComponents day];
NSInteger weekday = [weekdayComponents weekday];
public static DateTime NSDateToDateTime(MonoTouch.Foundation.NSDate date)
{
return (new DateTime(2001,1,1,0,0,0)).AddSeconds(date.SecondsSinceReferenceDate);
}
public static MonoTouch.Foundation.NSDate DateTimeToNSDate(DateTime date)
{
return MonoTouch.Foundation.NSDate.FromTimeIntervalSinceReferenceDate((date-(new DateTime(2001,1,1,0,0,0))).TotalSeconds);
}
Ok by using the above code you can turn the NSDate into a DateTime an do as you normally do on .Net World :) then with > DateTimeToNSDate you can revert it to a NSDate
hope this helps
Alex

Resources