So I have a unixtime datetime stamp. For arguments sake, lets say it's now at 23:49:24 on 21/02/2011 (GMT). This would be:
1298332164
Now, is there anyway to remove the seconds component from this? I'm writing this in Obj-C so currently I have:
NSDate *todayNow = [NSDate date];
int unixtimeNow = [todayNow timeIntervalSince1970];
And would end up with:
1298332140
Thanks
In Cocoa, you can do it like this:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger calendarUnits = NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit;
NSDateComponents *dateComps = [calendar components:calendarUnits fromDate:todayNow];
[dateComps setSecond:0];
NSDate *todayNowNoSeconds = [calendar dateFromComponents:dateComps];
What about 1298332164 / 60 * 60 ?
NSTimeInterval seconds = fmod([self timeIntervalSince1970], 60);
NSDate *secondsTrimmedDtae = [self dateByAddingTimeInterval:-seconds];
Note self refers to NSDate instance you have to replace self with your date obj.
Related
I need to get an NSDate object for 00:00(beginning of the day) from [NSDate date], let's say if currently it is 11:30am(returned by [NSDate date]), on 01/06/2012, now I need to have an NSDate for 00:00am on 01/06/2012.
I haven't tried this, but what is in my mind is:
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSDate *morningStart = [calendar dateFromComponents:components];
So I first get current date(say it is 01/06/2012), and construct a NSDateComponent for the date, then I set hour/minute/second to 0 and the year/month/day should not be changed(ie. 01/06/2012) then I create an NSDate for this component setting and can I get a date of 00:00:00 01/06/2012?
What you doing is correct, but when you NSLog morningStart the date will be displayed in GMT time zone
If you wanna make sure that the date is correct, convert it to NSString
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MMM-dd HH:mm:ss"];
NSString *strFromDate = [formatter stringFromDate:morningStart]; // this will return 2012-Jun-21 00:00:00
Converting NSDate to NSString can be helpful but if you need to keep a NSDate object for further processing, here is your solution to have your real morningStart NSDate object set at 00:00:00 time, with care of the timezone as well... As you will see you were not so far from the solution :
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
int timeZoneOffset = [destinationTimeZone secondsFromGMTForDate:now] / 3600;
[components setHour:timeZoneOffset];
[components setMinute:0];
[components setSecond:0];
NSDate *morningStart = [calendar dateFromComponents:components];
It's very easy to do this in iOS8 using startOfDayForDate:
let date = NSDate()
let calendar = NSCalendar.currentCalendar(calendarIdentifier: NSGregorianCalendar)
let dateAtStartOfDay = calendar.startOfDayForDate(date)
OR you may do it in the traditional way in Swift as follows:
let date = NSDate()
let calendar = NSCalendar.currentCalendar(calendarIdentifier: NSGregorianCalendar)
// Use a mask to extract the required components from today's date
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date)
let dateAtStartOfDay = calendar.dateFromComponents(components)!
print(dateAtStartOfDay)
(Note: NSDates are stored relative to GMT. So print will display the relative local time. A clear understanding of TimeZone's is essential to using NSDates properly.)
I want to get the Week number of the year from the date.I tried the code as follow but gives me a wrong week number.
My code for week number:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY-MM-dd"];
NSDate *date = [dateFormatter dateFromString:#"2012-09-15"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSLog(#"week: %i", [[calendar components: NSWeekOfYearCalendarUnit fromDate:date] weekOfYear]); //Display 38 instead of 37
}
Note: If i try with with [NSDate date] display the correct.
Help me to solve this..
Thank you,
ObjectiveC:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponent = [calendar components:(NSWeekOfYearCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
NSLog(#"%#",dateComponent);
Update
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponent = [calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:date];
NSLog(#"%#",dateComponent);
Swift:
let calendar = NSCalendar.currentCalendar()
let dateComponent = calendar.components([.WeekOfYear, .Day, .Month, .Year], fromDate: NSDate(timeIntervalSinceNow: 0))
print("weekOfYear \(dateComponent.weekOfYear)")
Swift 3 - Swift 5:
let component = Calendar.current.component(.weekOfYear, from: Date())
print("Week of Year \(component)")
[NSCalendar currentCalendar] gives you a Gregorian Calendar as default. You can use
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSISO8601Calendar];
to get an ISO 08601 conform calendar, which has week number 37 for your date.
Swift 3:
You need know last Date of selected month. Than check number of week for this week, and this will be your number of weeks in month
return Calendar.current.component(.weekOfMonth, from: lastDate ?? Date())
Updated code in ObjectiveC used Xcode version - 9.1 - :
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponent = [calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:[NSDate date]];
NSLog(#"%ld",(long)[dateComponent weekOfYear]);
I have been browsing the apple docs and stackoverflow for a while now, but I wasn't be able to find a correct answer for my problem.
I'll try to explain. In my app a user is able to create measurements on a specific time. The date and time of the measurement is important.
In my NSDate+Helper category I created the following helper methods:
- (NSDate *)dateByMovingToBeginningOfDay
{
unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self];
[parts setHour:0];
[parts setMinute:0];
[parts setSecond:0];
return [[NSCalendar currentCalendar] dateFromComponents:parts];
}
- (NSDate *)dateByMovingToEndOfDay {
unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self];
[parts setHour:23];
[parts setMinute:59];
[parts setSecond:59];
return [[NSCalendar currentCalendar] dateFromComponents:parts];
}
This methods helps me to get a range of measurements from a complete day:
NSDate *start = [[NSDate date] dateByMovingToBeginningOfDay];
NSDate *end = [[NSDate date] dateByMovingToEndOfDay];
NSMutableSet *measurementsSet = [trainingsPlan measurementsWithType:#"used" fromDate:start andToDate:end];
There is where my problem comes in. Let's say I add a measurement on my simulator at 2012-03-14 0:42:59 (GMT+1) -because that's the time displayed on my simulator- and save it in core data.
[NSDate date] at that moment is 2012-03-13 23:42:59 so NSDate *start = [[NSDate date] dateByMovingToBeginningOfDay]; gives me the start date of the day before. This is a problem.
My question, what is the best approach that it will work for users in all different timezones?
If you want to use the same data across multiple time zones then your only option is to use the same timezone in your app, no matter what time the iPad says. Generally you use UTC for this purpose (and is the default time zone that times are created and saved in).
If you just want it to match the local timezone, then you need to change your routines like this:
- (NSDate *)dateByMovingToBeginningOfDay
{
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* parts = [calendar components:flags fromDate:self];
[parts setHour:0];
[parts setMinute:0];
[parts setSecond:0];
return [calendar dateFromComponents:parts];
}
Update the second routine in the same way.
how do I set an existing NSDate's time?
That is I have a date (say current date/time), but then want to set this to a specific time (e.g. 11.23am) say. What is the quickest way to do this in objective C?
I'm looking at NSCalendar and see methods such as dateByAddingComponents:toDate:options:, and dateFromComponents:, but these don't seem to quite hit the mark for what I need here. For example:
dateFromComponents: - I would have to work out all components for this to work which seems like overkill
dateByAddingComponents:toDate:options: - I don't want to ADD in my case but rather "set" the time.
NSDate *date = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *components = [gregorian components: NSUIntegerMax fromDate: date];
[components setHour: 7];
[components setMinute: 59];
[components setSecond: 17];
NSDate *newDate = [gregorian dateFromComponents: components];
I use NSUIntegerMax instead of specific OR-combined bit masks because it's easier, but if you want to specify which data components to receive, be my guest.
iOS 7 Note: I'm putting this in a few of these questions because use of NSUIntegerMax no longer seems to work on iOS7, and using it caused me to chase my tail for about 3 hours. I just discovered that when I use NSUIntegerMax, NSDateComponentsignores set year. So for example this DOES NOT change the year:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSUIntegerMax fromDate:date];
[comps setYear:year];
return [gregorian dateFromComponents:comps];
Whereas this DOES:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger timeComps = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSTimeZoneCalendarUnit);
NSDateComponents *comps = [gregorian components:timeComps fromDate:date];
[comps setYear:year];
return [gregorian dateFromComponents:comps];
It may be an iOS7 bug or it may be that using NSUIntegerMax working was a fluke which no longer works. I will file a bug report and get a definitive answer.
Regardless, if you want to avoid unexpected consequences specify ALL the components else you might be chasing your tail!
Swift 2.0 version of how you'd set a given date to 8am
extension NSDate {
func setTo8AM() -> NSDate {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(([.Day, .Month, .Year]), fromDate: self)
components.hour = 8
return calendar.dateFromComponents(components)!
}
}
Apply this to set the Time from an another date to an existing Date
NSDate *today = [NSDate date]; // from which i need only "Year" "Month" "Date"
NSCalendar *calendar = [NSCalendar currentCalendar]
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit ) fromDate:today];
NSDate *timeDate = datePicker.date; // from which i need only "Hours" "Minutes" and "Seconds"
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:timeDate];
[dateComponents setHour:[timeComponents hour]];
[dateComponents setMinute:[timeComponents minute]];
[dateComponents setSecond:[timeComponents second]];
NSDate *newDate = [calendar dateFromComponents:dateComponents]; // New Date with My "Year" "Month" "Date" "Hours" "Minutes" and "Seconds"
NSLog(#"New Date: %#",newDate);
Here's a more generic Swift (v2.1.1) extension that builds on Andrew Schreiber's helpful answer.
extension NSDate {
func dateWithTime(hour: Int, minute: Int, second: Int) -> NSDate? {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(([.Day, .Month, .Year]), fromDate: self)
components.hour = hour
components.minute = minute
components.second = second
let newDate = calendar.dateFromComponents(components)
return newDate
}
}
A swift example. For my purposes, I wanted to get the date for around 12 noon tomorrow.
var tomorrow:NSDate = NSDate().dateByAddingTimeInterval(60*60*24); //60seconds*60minutes*12hours
var gregorian:NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!;
var unit : NSCalendarUnit = (NSCalendarUnit.YearCalendarUnit|NSCalendarUnit.MonthCalendarUnit|NSCalendarUnit.DayCalendarUnit|NSCalendarUnit.HourCalendarUnit|NSCalendarUnit.MinuteCalendarUnit);
var comps:NSDateComponents = gregorian.components(unit, fromDate: tomorrow);
comps.setValue(12, forComponent: NSCalendarUnit.HourCalendarUnit);
comps.setValue(0, forComponent: NSCalendarUnit.MinuteCalendarUnit);
var noon_tomorrow : NSDate = gregorian.dateFromComponents(comps)!;
I need to change a NSDate object. What I am basically doing is changing the year value.
for example:
NSString *someYear = #"2093";
NSDate *date = [NSDate date]; // Gets the current date.
... Create a new date based upon 'date' but with specified year value.
So with 'date' returning 2011-03-06 22:17:50 +0000 from init, I would like to create a date with 2093-03-06 22:17:50 +0000.
However I would like this to be as culturally neutral as possible, so it will work whatever the timezone.
Thanks.
Here's my code for setting the UIDatePicker limits for a Date Of Birth selection. Max age allowed is 100yrs
_dateOfBirth.maximumDate = [NSDate date];
//To limit the datepicker year to current year -100
NSDate *currentDate = [NSDate date];
NSUInteger componentFlags = NSYearCalendarUnit;
NSDateComponents *components = [[NSCalendar currentCalendar] components:componentFlags fromDate:currentDate];
NSInteger year = [components year];
NSLog(#"year = %d",year);
[components setYear:-100];
NSDate *minDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0];
_dateOfBirth.minimumDate = minDate;
Take a look at NSCalendar, especially components:fromDate: and dateFromComponents: methods.
I managed to figure the answer with the pointer Hoha gave me.
NSNumber *newYear = [[NSNumber alloc] initWithInt:[message intValue]];
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int unitFlags = NSYearCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents* dateComponents = [gregorian components:unitFlags fromDate:[NSDate date]];
[dateComponents setYear:[newYear intValue]];
NSDate *newDate = [gregorian dateFromComponents:dateComponents];
[newYear release];
Starting in iOS 8 you can set an specific date component. For example:
date = [calendar dateBySettingUnit:NSCalendarUnitYear value:year ofDate:date options:0];