Using specific time and day (NOT date) to activate 'if' function in Xcode - xcode

I'm current piecing together a streaming radio app for a show I work on and so far, it's okay - the streaming works once you push the 'Listen Live!' button and since that's the main aim, I'm happy. However, I'm trying to get clever now and set up an on-screen display that shows when the show is on the air; it's only on for two hours a week, so I thought it'd be nice to show when it's on and off via an on-screen display in the app. Nothing fancy... here's what I've got on screen so far:
1) A counting clock taken from here - EDIT: http://www.youtube.com/watch?v=pNVWST15pyc – that's really simple. Can't believe I didn't realise that changing the hh to HH makes it 24-hour... god, I'm so dumb.
2) A label to show just the day of the week, not the date or month, taken from here - NSCalendar to Display Weekday - as the app only needs to know whether it's Sunday (the on-air day) or not. EDIT: Made this work properly now because I'm an idiot who didn't link it up properly. :(
What I really want to do, however, is have the app set up two settings for an image view - an 'on air' and 'off air' switch - so that when it's between 8pm and 10pm on Sunday night, it shows the 'on air' image and when it's any other time, it shows the 'off air' one. I'm pretty sure that's an if statement but I'm not sure where to start trying to combine the clock and weekday bits to make that work. Can anyone make some suggestions please?
Also, since those times are GMT, I want to lock the app into GMT regardless of where in the world the user is so it relates directly to the show. I'm guessing I can do that using the timeZone:nil bit of the clock code by changing the 'nil' bit to 'Europe/London', but doing so just makes the whole thing crash out in spectacular fashion (I've tried it in various forms with no success). Again, suggestions would be massively appreciated.
Apologies for asking what may seem like simple questions - aside from some adult learning courses on Xcode, I'm a bit of a novice. :D

You should use the NSDateComponents object, which has a -weekday instance method (1 being Sunday for the gregorian calendar). Details on how to get started are in Apple's Date and Time Programming Guide. Here's a code sample that relates to what you are trying to do:
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];
NSDateComponents will also let you get and set (through so-called accessor methods) hour, minute, second, and timezone.
For the problem you described above, I would write a method like this:
- (BOOL)isShowOnAir {
BOOL onAir = NO;
NSDate *now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSTimeZoneCalendarUnit) fromDate:now];
[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSInteger day = [components day]; // Sunday == 1
if (day == 1) {
NSInteger hour = [components hour];
//NSInteger minute = [components minute]; -- not used but here's how to access it
if (hour == 20 || hour == 21) { // covers 8:00 - 9:59 PM
onAir = YES;
}
}
return onAir;
}

Related

NSDateComponenets giving wrong year value

I use some code to translate a list of dates into different sections by month:
- (NSString *) calculateSectionPeriod{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth) fromDate: [self userDate]];
NSString *tmp = [NSString stringWithFormat:#"%ld", ([components year] * 1000) + [components month]];
NSLog(#"Section period = %#", tmp);
return tmp;
}
The userDate is set from a NSDatePicker.
In most cases, this prints strings like "2015006" (June 2015) or "2017011" (November 2017). However, in some cases, for some users of my app, it ends up printing "15003" (and ends up causing some problems in Core Data). This is coming from their own reports, and I haven't been able to reproduce the issue on my own device, but it's clear to me that the problem is with this code.
Any reason where the 'year' component would print '15' instead of of '2015'? Is it by region or some language settings? I've tried setting different regions and languages, but haven't been able to reproduce the problem myself.

Xcode time difference in days, hours, minutes and seconds

First of all: I want to say happy new year to everybody reading this!! May 2015 be a great year for all of us :-).
I'm busy with making a function which calculates the time difference between two dates. To be more precise: the time between a time and date given and the current time and date.
So the user selects a date in the past and then the program shows the time difference between the given date and todays date in a timer like so: "hh:mm:ss"
It works okay and updates every second when i select a time of todays date (01-01-2015 10:00:00), but when selecting a date and time in the past (31-12-2014 17:00:00) and compare it to todays date where the time is earlier than yesterday (01-01-2015 14:01:01), it gives me a negative time like a sort of countdown timer: -2:-59:-59.
But i want it to show the opposite of it: 21:01:01 and if possible if it exceeds the 24:00:00, just count on. For example 25:12:39.
This is the code that calculates the difference:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MM-YYYY HH:mm:ss"];
NSDate *date1 = [df dateFromString:[NSString stringWithFormat:#"30-12-2014 %#", startedTime]];
NSDate *date2 = [df dateFromString:[NSString stringWithFormat:#"31-12-2014 %#", [self getCurrentTime]]];
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
int hours = (int)interval / 3600; // integer division to get the hours part
int minutes = (interval - (hours*3600)) / 60; // interval minus hours part (in seconds) divided by 60 yields minutes
int seconds = (interval - (hours*3600) - (minutes*60)); // interval minus hours part (in seconds) divided by 60 yields minutes
NSString *timeDiff = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
_workingTime.text = [NSString stringWithFormat:#"%#",timeDiff];
Can someone please help?
[df setDateFormat:#"dd-MM-yyyy hh:mm:ss"];
Try after this change of the format string!
And this.. finally.
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
if( interval < 0 ) {
interval = [date1 timeIntervalSinceDate:date2];
}
More about date formats here

How to calculate and display 4 other days from the day i add in date picker and set local notification to it?

In my App, When i select a day in the datepicker it should automatically calculate and display 4 other days and also it should notify on the corresponding days. For Eg. if i enter 19-08-2014, it should calculate and display the 3rd day, the 7th day, the 14th day and the 21st day from 19-08-2014(the day i entered in datepicker).
How would i achieve this. Any help would be greatly appreciated.
I have added my current code for your reference. This doesnt serve my purpose.
Kindly Help.
(IBAction)save:(UIButton *)sender {
NSDate *pickerDate = [self.picker date];
UILocalNotification *localNotif = [[UILocalNotification alloc]init];
//localNotif.alertBody = _enterText.text;
localNotif.alertBody = #"Please Take Your Rabipur Dosage";
localNotif.fireDate = pickerDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.soundName = (UILocalNotificationDefaultSoundName);
localNotif.applicationIconBadgeNumber = 1;
//localNotif.repeatInterval = NSDayCalendarUnit;
[[UIApplication sharedApplication]scheduleLocalNotification:localNotif];
[self dismissViewControllerAnimated:YES completion:nil];
}
Create an NSDateComponents object with the date difference you want to add, and add it to pickerDate via NSCalendar -dateByAddingComponents:toDate:options. Then create your notification based on the resulting date.
In this case, something like this:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:3];
NSDate *reminderDate = [gregorian dateByAddingComponents:offsetComponents toDate:pickerDate options:0];
Repeat for 7th, 14th, and 21st day.

Why is UIDatePicker in countdown mode 1 hour behind?

If I set the UIDatePicker's date in countdown mode to "1970-01-01 00:05:00 +0000" it shows [ 1hour | 5min ] - why is that?
Set the date (in a different class):
_countdownTime=[[NSDate alloc] initWithTimeIntervalSince1970:5*60];
Create picker and assign date:
//setup a date picker as countdown picker
UIDatePicker *countdownPicker = [[UIDatePicker alloc] init];
[countdownPicker setDate:[NSDate date]];
[countdownPicker setDatePickerMode:UIDatePickerModeCountDownTimer];
[countdownPicker setMinuteInterval:5];
[countdownPicker addTarget:self action:#selector(updateCountdownTimeText:) forControlEvents:UIControlEventValueChanged];
[countdownPicker setDate:[myAction getCountdownTime]];
(This is at least somewhat a guess... I'm not an iOS expert at all.)
Well it sounds like the problem is precisely because you're using a time zone which is GMT+1 - or was in January 1970, anyway.
Basically I think the UIDatePicker is showing you the local time of the given NSDate, with the relevant time zone applied. initWithTimeIntervalSince1970 initializes a date with the given number of seconds since the Unix epoch, which is midnight UTC.
I suggest you set the time zone to UTC:
[countdownPicker setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
Then hopefully it'll show what you expected...

Calculate seconds between current time and next event

This should be simple, but it's proving challenging for me. I'd like to know the best approach to calculating the difference in seconds between [NSDate date] and a future event x seconds from that time. There are several different types of event, and each event may occur several times a day, and at different times, depending what day of the week it happens to be.
What I am trying to do is have the user select an event type from a picker and then set an alarm in Notification Center for the next occurrence of that event based on their selection. I have everything working fine, except for the seconds calculation.
So, for example, let's say it's 9am on a Monday. I'd like to determine how many seconds it would be between now and a user selected event that regularly occurs every Tuesday, Thursday, and Saturday at 10am, 4pm, and 11pm on each day, or on Sunday at 1pm. How would you approach this most efficiently?
When you're talking about a time or date like "next Thursday at 1 PM", that's information that only makes sense in the context of a calendar. NSDate is not going to provide you with much help. It would perhaps be more appropriately named NSPointInTime. It's just a number of seconds that have passed from some earlier, arbitrary reference point in time. It has no notion of weekdays, ante/post meridiem, or even hour of the day.
The two objects that do know about those sorts of thing are NSDateComponents and NSCalendar. Working together, they can create an NSDate from a specification like "next Thursday at 1PM".
You can decompose any date into components using -[NSCalendar components:fromDate:], and you can then use other NSDateComponents objects to perform arithmetic on the individual pieces of information. Find the weekday of today, for example, and its difference from Thursday. Then use -[NSCalendar dateByAddingComponents:toDate:options:] to create a new date based on that offset.
#interface NSCalendar (NextWeekday)
- (NSInteger)maxWeekday;
- (NSDate *)dateFromComponents:(NSDateComponents *)comps
forNextWeekday:(NSInteger)weekday
atHour:(NSInteger)hour;
#end
#implementation NSCalendar (NextWeekday)
- (NSInteger)maxWeekday
{
return [self maximumRangeOfUnit:NSWeekdayCalendarUnit].length;
}
- (NSDate *)dateFromComponents:(NSDateComponents *)comps
forNextWeekday:(NSInteger)weekday
atHour:(NSInteger)hour
{
NSInteger diff = weekday - [comps weekday];
if( diff < 0 ){
diff += [self maxWeekday];
}
NSDateComponents * weekdayOffset = [NSDateComponents new];
[weekdayOffset setWeekday:diff];
[comps setHour:hour];
return [self dateByAddingComponents:weekdayOffset
toDate:[self dateFromComponents:comps]
options:0];
}
#end
#define GREGORIAN_THURSDAY 5
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * wednesday = [NSDateComponents new];
[wednesday setDay:3];
[wednesday setWeekday:4];
[wednesday setMonth:6];
[wednesday setYear:2013];
NSDateComponents * friday = [NSDateComponents new];
[friday setDay:5];
[friday setWeekday:6];
[friday setMonth:6];
[friday setYear:2013];
NSDateComponents * now = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit
fromDate:[NSDate date]];
NSDateComponents * lastSatOfDecember = [NSDateComponents new];
[lastSatOfDecember setDay:29];
[lastSatOfDecember setWeekday:7];
[lastSatOfDecember setMonth:12];
[lastSatOfDecember setYear:2012];
NSLog(#"From Wednesday: %#", [cal dateFromComponents:wednesday
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"From Friday: %#", [cal dateFromComponents:friday
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"From now: %#", [cal dateFromComponents:now
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"Crossing over the year: %#", [cal dateFromComponents:lastSatOfDecember
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
}
return 0;
}

Resources