NSPredicate with NSDate and repeats (like Calendar app) - objective-c

I have an entity "Event" witch contains two properties: date (NSDate) and repeat (NSInteger - 0 = NONE, 1 = DAILY, 2 = WEEKLY, 3 = MONTHLY, ...).
Does anyone knows how can I filter events by repeats passing a date ?
Example:
First event: 01-01-2010 / weekly
Second event: 10-02-2010 / monthly
Current date: 10-06-2010
Request:
Get all events where Event.date == "Current date" OR Event.date.day == "Current date".day if Event.repeat == monthly
Returned event:
Second event
I hope someone understand what I'm trying to explain :s

The problem here is that NSDate doesn't have a day (or any other similar) property. If it did, your predicate would work as written.
Data and time programming is deceptively complex under the hood. For example, in common usage, the phrase "same date" means the exact same calendar day. However, from the codes perspective it also means the same week, month and year because days are no more significant to code than any other arbitrary calendar division. Even in ordinary usage, "day" can refer to a specific range of hours e.g. Saturday, August 21 2010 or it can refer to any arbitrary range of 24 hours as in, "within a day." Which one do you need for this app?
NSDate is really an object wrapper around a microsecond accurate timestamp. It has methods for converting to strings and for creating and comparing timestamps but it doesn't understand calendar attributes such seconds, minutes, hours, days, weeks, month, or years. That is what NSCalendar is for and Core Data does not innately support that class as a data type as doing so for all possible calendars would be to complex.
If calendar attributes are required in a model, you need to create an custom entity that models a calendar date. Set the entities attributes to calendar attributes you need to model and then a relationship to the object that needs the calendar date as a property e.g.
CalendarDate{
date:NSDate
minute:int
hour:int
day:int
month:int
year:int
events<--(required,nullify)-->>Event.date
}
You can create a custom class for the entity and provide a method that automatically populates the object based on the passed NSDate and any calendar you choose.
Now your predicate is easy.
NSPredicate *myPred;
myPred=[NSPredicate predicateWithFormat:#"(date.date==%# or date.day==%i) AND repeat=%i", currentDate, 45, kMonthly];
This seems like it is cumbersome but it is required owing to the true complexity of calendar dates. There simply isn't an easy way to handle date and time calculations and comparisons for all uses.

I am not certain this can be done at the SQLite level. It certainly can be done once your events are pulled into memory but that, I suspect, defeats your goal.
There might be some clever way to de-normalize the data and thereby create a situation that can be filtered.
For example, if you had the day of month and month pulled out into integer fields you might be able to devise a way to determine based on those if things align. It is not coming to me directly but I would definitely look in that direction for a solution.
Another alternative, one that calendars tend to use, is to create dependent events for the specific dates coming up. When the event is created you create all of the dependent events so that you are just filtering on a date. Nasty to be sure.
Last option is to pull all events into memory and calculate from there.

Related

IBM Domino: View formula with #now

There are some views which has columns with formula including #now. These columns are used to calculate days from now. But these views are so slow. I just need to get documents in specific category from result of view. Are there any setting in view to get category's document before calculate days? Or do I have to remove days columns from view and write an agent to add&calculate days columns to the view's result?
"Or [do] I have to remove days columns from view and write an agent to add&calculate days columns to the view's result?"
Yes. #Now in a view formula is a recipe for poor performance. Create a scheduled agent that runs once per day and updates a field on the document then show that field in the view.
This column formula allows you to add a Today value without using #Today and hence lots of continual processing;
TodayDateString:= "Today";
Today := #TextToTime(TodayDateString);
#Abs(#Integer((Today - DateToCompare) / (60 * 60 * 24)))
Already answered, but I still felt the need to add my thoughts.
If you can afford to touch your documents every day (e.g. it's just a web on a single or clustered server) then I'd seriously consider writing an agent that updates a "NumDaysOld" field.
The reason why performance is slow if you have #Now or #Today in a view selection or column formula is because the indexer then knows that it is time-dependent and therefore doesn't store the view index (or maybe just doesn't store the entire index, I'm not sure), causing it to rebuild every time it's accessed.
If you cheat this by using #TextToTime("Today") then your view indexes risk being out of date because if a document doesn't change for n days, the view doesn't change for n days, and the indexer isn't triggered...
Perhaps a best practice would be to write an agent to change the column formula every day so that instead of #Today, use a literal date (by using square brackets, like [5/29/2018]) and then write an agent to change that column formula every day. I've never tried that because that wasn't available to me when I had needed to do something like this. (It's been a long time.) Instead I have resolved this need by:
writing an agent that modified each document to update the age of the document, or
making folders for "< 1 month", "2 to 6 months", etc., and had a daily agent that would populating/correct the folders, or
avoiding the problem by having a view of open documents sorted by date and then trying to convince the end-users that was close enough! :-P (not proud of this one)

Qlikview line chart with multiple expressions over time period dimension

I am new to Qlikview and after several failed attempts I have to ask for some guidance regarding charts in Qlikview. I want to create Line chart which will have:
One dimension – time period of one month broke down by days in it
One expression – Number of created tasks per day
Second expression – Number of closed tasks per day
Third expression – Number of open tasks per day
This is very basic example and I couldn’t find solution for this, and to be honest I think I don’t understand how I should setup my time period dimension and expression. Each time when I try to introduce more then one expression things go south. Maybe its because I have multiple dates or my dimension is wrong.
Here is my simple data:
http://pastebin.com/Lv0CFQPm
I have been reading about helper tables like Master Callendar or “Date Island” but I couldn’t grasp it. I have tried to follow guide from here: https://community.qlik.com/docs/DOC-8642 but that only worked for one date (for me at least).
How should I setup dimension and expression on my chart, so I can count the ID field if Created Date matches one from dimension and Status is appropriate?
I have personal edition so I am unable to open qwv files from other authors.
Thank you in advance, kind regards!
My solution to this would be to change from a single line per Call with associated dates to a concatenated list of Call Events with a single date each. i.e. each Call will have a creation event and a resolution event. This is how I achieve that. (I turned your data into a spreadsheet but the concept is the same for any data source.)
Calls:
LOAD Type,
Id,
Priority,
'New' as Status,
date(floor(Created)) as [Date],
time(Created) as [Time]
FROM
[Calls.xlsx]
(ooxml, embedded labels, table is Sheet1) where Created>0;
LOAD Type,
Id,
Priority,
Status,
date(floor(Resolved)) as [Date],
time(Resolved) as [Time]
FROM
[Calls.xlsx]
(ooxml, embedded labels, table is Sheet1) where Resolved>0;
Key concepts here are allowing QlikView's auto-conatenate to do it's job by making the field-names of both load statements exactly the same, including capitalisation. The second is splitting the timestamp into a Date and a time. This allows you to have a dimension of Date only and group the events for the day. (In big data sets the resource saving is also significant.) The third is creating the dummy 'New' status for each event on the day of it's creation date.
With just this data and these expressions
Created = count(if(Status='New',Id))
Resolved = count(if(Status='Resolved',Id))
and then
Created-Resolved
all with full accumulation ticked for Open (to give you a running total rather than a daily total which might go negative and look odd) you could draw this graph.
For extra completeness you could add this to the code section to fill up your dates and create the Master Calendar you spoke of. There are many other ways of achieving this
MINMAX:
load floor(num(min([Date]))) as MINTRANS,
floor(num(max([Date]))) as MAXTRANS
Resident Calls;
let zDateMin=FieldValue('MINTRANS',1);
let zDateMax=FieldValue('MAXTRANS',1);
//complete calendar
Dates:
LOAD
Date($(zDateMin) + IterNo() - 1, '$(DateFormat)') as [Date]
AUTOGENERATE 1
WHILE $(zDateMin)+IterNo()-1<= $(zDateMax);
Then you could draw this chart. Don't forget to turn Suppress Zero Values on the Presentation tab off.
But my suggestion would be to use a combo rather than line chart so that the calls per day are shown as discrete buckets (Bars) but the running total of Open calls is a line

Core Data or NSDictionary with multiple date entries (about 800+ each year)? What would be the most easy to implement?

I'm trying to figure the best approach to solve this problem.
--
I have a "History" table that,
lists ALL years that have data.
If a user clicks a given Year, it segues to a new Table and,
lists ALL months that have data.
Clicking a given month, shows a new table that,
lists ALL days that have data.
Clicking a specific day, shows a list of one or multiple Time Stamps.
--
What is the best approach to solve this?
If user creates a Time Stamp. I need to insert it with today's date.
I also need to have the ability that if a user,
Deletes a given year. Everything in that year is deleted.
That same way,
Deleting a month, deletes everything in that month, for it's particular year.
And so on, to the point where the user should be able to delete Individual Time Stamps.
--
I thought I would Use a Dictionary with key for the "year". 2012, 2013, ...
And each retrieving another Dictionary with key for the "month", 1, 2, 3, 4, ...
And so on ... and so on ...
I also thought I could make a model using Core Data.
A Class Year representing the "Year" entity, having a relation to many possible Months, and each month, having a relation to many possible days, and days to Time *Stamps*.
And last,
I thought of creating a model with only two Entities.
Entries, with only one attribute "Date", that has a to-many relationship to "Time Stamps", receiving All the possible Time Stamps for that given day.
I am new to iOS programming. So this is all theory for me. But I did follow some Core Data tutorials and others working with NSDictionaries, protocols delegates and so on.
The "Dig In" approach as I go trough, seems more elegant. Specially because I think I could delete a particular given object in a cascade manner?
Do any of these make sense? Or is there a more obvious easy way to go about it? Also, please consider in the answer what would be easier to implement if a user chooses to delete a given entry in the "tree"
Any help is most appreciated.
Thank you advance!
Nuno
If you are going to rely on Core Data or any database engine, the best way to solve this is to use the database itself.
I see two possible solutions (there is more of course). The first, the simplest :
Entity
- timestamp
- year
- month
- day
- all_the_stuff_you_need
Make year, month and day readonly, updated along timestamp. Indexes: year, year+month, year+month+day. Easy call.
That way, you can very simple query the database, asking it to return the entities you need and only the entities you need.
A more complex setup would be:
Entity
- timestamp
- all_the_stuff_you_need
- year -> Year
- month -> Month
- day -> Day
Year
- year
- entities ->> Entity
Month
- month
- entities ->> Entity
Day
- day
- entities ->> Entity
So basically, 3 data domains for the years, months and days, months and days being immutable.
That structure is more complex, but it gives a better view of your data. You have a direct access to more information on your data as the data domains are explicit and well defined.
A third solution would be to create a date entity with year, month and day, with one entry per day. A middle ground between the two solutions above. Less interesting I think, but hey, it may suit your needs anyway.

Repeated events in Eventbrite API

I noticed that when I search future events via event_search method, sorted by date, that first events in result-set have start date from past. Problem with these events is that they are repeatable events (e.g. weekly), but API does not return events' recurrence type (daily, weekly, monthly, other). Method should at least return next event start date and recurrance type.
Hidden feature:
Add "display=repeat_schedule" to your API requests to reveal a series of start_date, end_date pairs for each repeating instance.
Unfortunately, Eventbrite's "repeating events" feature (available on their website) is not totally compatible with their API services:
Most storage models have an associated identifier or 'handle' to reference each asset or resource. In REST-speak these identifiers are known as 'resource ids'.
Eventbrite's repeating events share a single event id, and they include a string that describes the schedule when they repeat.
The head of the chain of repeating events is returned, with a "repeats" attribute that is set to "yes". And, the "repeat_schedule" attribute should now be present on all repeating events.
The string that is revealed will have a different format depending how the event is configured to repeat:
Daily repeating events:
"daily-4-07/26/2012" - every fourth day, from the date/time of the
start_date until 2012-07-26.
"daily-mf-07/26/2012" - every Monday
through Friday, from the start_date day/time until "2012-07-26"
Weekly repeating events:
"weekly-3-Y,N,N,N,N,N,N-09/16/2012" - every 3rd week, on each day marked with a "Y" until "2012-09-16"
Monthly repeating events:
"monthly-2-10-06/30/2012" - every second month, on the 10th day of the month until "2012-06-30"
"monthly-2-second/sat-06/30/2012" - every second month, on the second Saturday of that month, until "2012-06-30".
Custom repeat schedule (not fully supported):
"custom-3199915" - This format is really rare. Unfortunately, these events can not be easily summarized using a single string.
This bug needs to be fixed by EventBrite
However Would this work has a temp workaround? I would work in some examples I have seen.
I make request for events on March 17, 2012
I get back a past date
<repeats>yes</repeats>
<start_date>2011-12-04 09:30:00</start_date>
<end_date>2011-12-04 10:30:00</end_date>
Can I assume this is a repeating event that occcurs on March 17, 2012
at the same times?
There's a new endpoint that can be used to fetch all the events that are part of a series, the only values required are: OAuth Token and the event_series_id which is the parent event ID or the ID of the event where the series was created.
This is the endpoint:
GET - https://www.eventbriteapi.com/v3/series/{event_series_id}/events/
Replace {event_series_id} with your event series ID.
More details at: https://www.eventbrite.com/platform/api#/reference/event/list/list-events-by-series

How do I increment a date by one month?

I have a date and I want to increment it by 1 month. How can I do this?
I'm new to iPhone programming. Can this be done or do I have to implement it myself?
You really need to use an NSCalendar for this type of activity, as this has methods like -dateByAddingComponents:toDate:options: which will let you add "components" (NSDateComponents that represent 1 month or 1 year, etc. for example) onto an existing calendar date.
For some general background reading, you might also want to take a look at the Date and Time Programming Guide as it covers some of this, albeit quite briefly.