This is probably a simple solution but does anyone know how to delay the NSDate change past midnight? Any insight would be really helpful, thanks!
Edit:
I am currently getting the date this way and displaying a locations data based on that day. But, much like the NSDate is logically supposed to work, it switches to the next day at midnight. I want the date to change at 3am instead of at 12am.
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"EEEE"];
today = [f stringFromDate:[NSDate date]];
Should I just use the time instead of using NSDate? I am a bit of a noob to iOS so any insight would be helpful. Thanks for your responses already.
I must admit that I do not yet understand why you want to display a "wrong" weekday
name, but the following code should do what you want. This is only one of various ways
to achieve your task.
Convert date to "date components:"
NSCalendar *cal = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit;
NSDateComponents *comp = [cal components:unitFlags fromDate:[NSDate date]];
Subtract one day if necessary:
if (comp.hour < 3) {
comp.day -= 1;
}
Convert adjusted components back to date:
NSDate *adjustedDate = [cal dateFromComponents:comp];
Your original code, now using the adjusted date:
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"EEEE"];
NSString *today = [f stringFromDate:adjustedDate];
Related
Background: I have dates stored in files.
What I would like to do: I would like to take the difference between two dates in seconds. I can't find any way to do it. My date format looks like that:
2015-23-02-12-23-43
Try this out:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-mm-dd-hh-mm-ss"];
NSDate *date = [dateFormatter dateFromString:string1];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:date];
NSInteger hour = [components hour];
NSInteger minute = [components minute];
Try this:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:EnterYourStringHere];
NSString *str = [dateFormatter stringFromDate:date];
If all you need is seconds then use
NSTimeInterval dateInterval = [date timeIntervalSince1970];
Then
NSString secondsString = [NSString stringWithFormat: #"%.0f", dateInterval];
EDIT:
If you have a file full of date strings that look like your example, 2015-23-02-12-23, then you could use code like this:
NSDateFormatter *myFormatter = [[NSDateFormatter alloc] init];
[myFormatter setDateFormat:#"yyyy-mm-dd-hh-mm-ss"];
//an example - you'll read from your file
NSString *aDateString = #"2015-23-02-12-23";
NSDate aDate = [myFormatter dateFromString: aDateString];
NSTimeInterval dateSeconds = [aDate timeIntervalSince1970];
That will give you dateSeconds as a double precision floating point number, which is the norm for numeric date calculations since it deals with fractions of seconds. You can then do numeric comparisons of date's time intervals.
Note that most UNIX systems use the numeric values returned by the timeIntervalSince1970 method, but Mac and iOS uses numeric date values returned by the method timeIntervalSinceReferenceDate. The two methods have different "epoch dates", or dates where they start counting from zero.
timeIntervalSince1970 uses midnight on Jan 1, 1970 (GMT)
timeIntervalSinceReferenceDate uses midnight on Jan 1, 2001 (GMT)
Which you use is up to you, just be sure to use the same method in all cases.
By the way, your date string format is horrible. having all those 2 digit numbers separated by dashes doesn't give the reader any way to tell apart month/day/hours/minutes/seconds. It's all a jumble. You'd be much better off using a standard date format.
In the US it's common to display dates in the form mm/dd/yyyyy (or yyyy/mm/dd, or even yyyy/dd/mm), and times as hh:mm:ss, so in "mm/dd/yyyyy hh:mm:ss" format you'd get:"09/02/2015 13:09:39" (I'm using human-readable date format strings for discussion, not those intended to set up a date formatter.)
I am making an app to use at school and I want to make a countdown timer to countdown the amount of time between now and the end of school, which for me is 3:00. For example, at 11:15, it will read 3:45.
So far, I have figured out how to make the countdown timer and I have the following code: countdownTimer.text = [Formatter stringFromDate: [NSDate date]];
This code doesn't actually work yet, but I think it will work if I figure out how to subtract the current time from a set time and then use that value where date is, however I am open to other suggestions on how to approach the problem.
You can use NSCalendar method dateBySettingHour:minute:second: to get the NSDate object associated with 3pm today:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDate *schoolOut = [calendar dateBySettingHour:15 minute:0 second:0 ofDate:now options:0];
There are lots of different ways to get the NSDate object associated with 3pm today, but the above is just one example. You could also use components:fromDate of NSCalendar to extract the NSDateComponents of now, then adjust the hour, minute and second and then create a new NSDate object using dateFromComponents (also a NSCalendar method).
Anyway, once you have a NSDate object that represents your target date/time, you can then use NSDateComponentsFormatter to display the time interval between two dates in a nice format.
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.allowedUnits = NSCalendarUnitHour | NSCalendarUnitMinute;
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
NSString *string = [formatter stringFromDate:now toDate:schoolOut];
You can adjust the unitsStyle and zeroFormattingBehavior to adjust the format of the string.
After searching through SO but apart from this question I found no solutions. I'm thinking about creating a method that would accept the int of the week number and the int of the year and that would return an NSString with the name of the month:
- (NSString *)getMonthNameFromNumber:(int)weekNumber andYear:(int)year
But I can't find a way to approach this problem. Would be glad if anyone could help with advices.
Something like this will do
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year {
NSDateComponents * dateComponents = [NSDateComponents new];
dateComponents.year = year;
dateComponents.weekOfYear = week;
dateComponents.weekday = 1; // 1 indicates the first day of the week, which depends on the calendar
NSDate * date = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM"];
return [formatter stringFromDate:date];
}
Note that this is dependent on the current calendar set in the device preferences.
In case this doesn't fit your needs, you can provide a NSCalendar instance and use it to retrieve the date instead of using currentCalendar. By doing so you can configure things like which is the first day of the week and so on. The documentation of NSCalendar is worth a read.
If using a custom calendar is a common case, just change the implementation to something like
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year {
[self monthNameForWeek:week inYear:year calendar:[NSCalendar currentCalendar]];
}
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year calendar:(NSCalendar *)calendar {
NSDateComponents * dateComponents = [NSDateComponents new];
dateComponents.year = year;
dateComponents.weekOfYear = week;
dateComponents.weekday = 1; // 1 indicates the first day of the week, which depends on the calendar
NSDate * date = [calendar dateFromComponents:dateComponents];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM"];
return [formatter stringFromDate:date];
}
As an unrelated side note, you should avoid get for methods names, unless you are returning a value indirectly.
With anything to do with dates, you need to involve a calendar. Your question assumes the Gregorian Calendar, but I suggest you change your method declaration to:
- (NSString*)monthNameFromWeek:(NSInteger)week year:(NSInteger)year calendar:(NSCalendar*)cal;
From this, there is also the ambiguity of which day we're talking about. For example (this hasn't been checked), week 4 of 2015 may contain both January and February. Which one is correct? For this example, we'll use a weekday of 1, which indicates Sunday (in the UK Gregorian Calendar), and we'll use whatever month this falls in to.
As such, your code would be:
// Set up our date components
NSDateComponents* comp = [[NSDateComponents alloc] init];
comp.year = year;
comp.weekOfYear = week;
comp.weekday = 1;
// Construct a date from components made, using the calendar
NSDate* date = [cal dateFromComponents:comp];
// Create the month string
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMMM"];
return [dateFormatter stringFromDate:date];
I calculate number of days between two dates:
NSDateComponents *datesDiff = [calendar components: NSDayCalendarUnit
fromDate: someDate
toDate: currentDate
options: 0];
But this method has one disadvantage - it doesn't take in account time zone.
So, for example, if I'm in +2GMT and local time is 1:00AM, current date is yesterday.
How to compare dates in specified time zone (without 'hacking')?
PS: Preventing answers with calculation of time difference, I need difference of actual days:
yesterday 23:00 vs. today 1:00 - 1 day
yesterday 1:00 vs. today 23:00 - 1 day
today 1:00 vs. today 23:00 - 0 days
(all this in current time zone)
I don't know if it meets your criteria of not being hacky, but a fairly simple way seems to be defining a GMT adjusted date something like this:
NSDate *newDate = [oldDate dateByAddingTimeInterval:(-[[NSTimeZone localTimeZone] secondsFromGMT])
See this question for more details.
Why don't you configure the dateformatter to default all dates to GMT time and then compare.
NSDate *now = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"GMT"]; // Sets to GMT time.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setCalendar:gregorianCalendar];
[formatter setTimeZone:timeZone];
[formatter setDateFormat:#"yyyyMMddHH"];
NSString *dateString = [formatter stringFromDate:now];
// do whatever with the dates
[gregorianCalendar release];
[formatter release];
I have been racking my brains on this one looking for a quick solution.
I need to fire off a NSTime at a specific time based on the current time in a specific time zone.
For example, I get the current time in PST:
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"HH:mm:ss";
NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
[cal setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"PST"]];
NSDateComponents * comps = [cal components:NSHourCalendarUnit fromDate:now];
I see that the time is 2 (14) getting [comps hour] and I need to fire a timer at 2:30PM (14:30) on that day. I need help converting it back and doing the math to say how long it is before the timer fires. I will be setting up several different timers based on the current time. While I am looking at the time in PST I know that the timers and setting of the time is done in GMT. That's another twist...
Thanks in advance...
I solved the problem myself.. But thanks for the tips...
if ([date earlierDate:newDate] == date) // it is before 7AM... fire at 7AM
and so on....