NSDate with date component from one and time component from another NSDate - ios

I have two UIDatePicker controls in my app, one configured with UIDatePickerModeDate and one with UIDatePickerModeTime.
I want to configure a NSDate object with the date from UIDatePicker one and the time from the second one ... how?
Thanks,
Mark

Assume date1 and date2 are your two NSDate values. date1 contains your date components and date2 contains your time components. Here's how you would combine them together:
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Extract date components into components1
NSDateComponents *components1 = [gregorianCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:date1];
// Extract time components into components2
NSDateComponents *components2 = [gregorianCalendar components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
fromDate:date2];
// Combine date and time into components3
NSDateComponents *components3 = [[NSDateComponents alloc] init];
[components3 setYear:components1.year];
[components3 setMonth:components1.month];
[components3 setDay:components1.day];
[components3 setHour:components2.hour];
[components3 setMinute:components2.minute];
[components3 setSecond:components2.second];
// Generate a new NSDate from components3.
NSDate *combinedDate = [gregorianCalendar dateFromComponents:components3];
// combinedDate contains both your date and time!
For iOS 8.0 +
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// Extract date components into components1
NSDateComponents *components1 = [gregorianCalendar components:(NSCalendarUnit)(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay)
fromDate:date1];
// Extract time components into components2
NSDateComponents *components2 = [gregorianCalendar components:(NSCalendarUnit)(NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond)
fromDate:date2];
// Combine date and time into components3
NSDateComponents *components3 = [[NSDateComponents alloc] init];
[components3 setYear:components1.year];
[components3 setMonth:components1.month];
[components3 setDay:components1.day];
[components3 setHour:components2.hour];
[components3 setMinute:components2.minute];
[components3 setSecond:components2.second];
// Generate a new NSDate from components3.
NSDate * combinedDate = [gregorianCalendar dateFromComponents:components3];
// combinedDate contains both your date and time!

In Swift:
let calendar = NSCalendar.currentCalendar()
let date1 = NSDate() // PickerDateMode
let date2 = NSDate() // PickerHourMode
let componentsOne = calendar.components([.Year, .Month, .Day], fromDate: date1)
let componentsTwo = calendar.components([.Hour, .Minute], fromDate: date2)
let totalComponents = NSDateComponents()
totalComponents.year = componentsOne.year
totalComponents.month = componentsOne.month
totalComponents.day = componentsOne.day
totalComponents.hour = componentsTwo.hour
totalComponents.minute = componentsTwo.minute
let finalDate = calendar.dateFromComponents(totalComponents)

NSCalendar *calendar= [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSCalendarUnit unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDate *date = [NSDate date];//datapicker date
NSDateComponents *dateComponents = [calendar components:unitFlags fromDate:date];
NSInteger year = [dateComponents year];
NSInteger month = [dateComponents month];
NSInteger day = [dateComponents day];
NSInteger hour = [dateComponents hour];
NSInteger minute = [dateComponents minute];
NSInteger second = [dateComponents second];

Update to Swift 4 and 4.1
func combineDateAndTimeToOneDate() {
let datefrmter = DateFormatter()
datefrmter.dateFormat = "dd/MM/yyyy"
let dateFromString = datefrmter.date(from: lblDate.text!)
datefrmter.dateFormat = "h:mm a"
let timeFromString = datefrmter.date(from: lblTime.text!)
let calendar = NSCalendar.current
let componentsOne = calendar.dateComponents([.year,.month,.day], from: dateFromString!)
let componentsTwo = calendar.dateComponents([.hour,.minute,.second,.nanosecond], from: timeFromString!)
let totalComponents = NSDateComponents()
totalComponents.year = componentsOne.year!
totalComponents.month = componentsOne.month!
totalComponents.day = componentsOne.day!
totalComponents.hour = componentsTwo.hour!
totalComponents.minute = componentsTwo.minute!
totalComponents.second = componentsTwo.second!
totalComponents.nanosecond = componentsTwo.nanosecond!
let finalDate = calendar.date(from: totalComponents as DateComponents)
print(finalDate)
}
Hope it helps!

Related

how to get correct NSDate from NSString without using dateFormatter

because NSDateformatter cannot use custom calendar, so for a calendar like:
NSCalendar *ISO8601 = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
[ISO8601 setMinimumDaysInFirstWeek:7];
[ISO8601 setFirstWeekday:2];
If we need the weekofYear,
This calendar will translate 2015-04-26 16:00:00 as 2015-16th week.
So I will get a string as 2015-16th week.
Then how can I convert string 2015-16th week to a correct NSDate or DateComponents, so if you convert this new NSDate or dateComponents, it will not loose the correctness?
- (NSDate *) dateByAddingWeeks:(NSInteger)dWeeks {
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [[NSDateComponents alloc] init];
NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitTimeZone;
components = [gregorian components:unitFlags fromDate:self];
components.day = components.day + 7 * dWeeks;
return [gregorian dateFromComponents:components];
}
Not sure.Are you looking for these kind of utility function?

How to compose date from first NSDate and time from second NSDate into one NSDate?

I need one thing:
create one output NSDate that includes both of them with format: "yyyy-MM-dd HH:mm:00", where yyyy-MM-dd is from first NSDate and HH:mm:00 is from second NSDate
You can easily achieve this by creating a convenience initializer, like this:
convenience init(date: NSDate?, time: NSDate?) {
var combinedDate = NSDate()
if let date = date {
if let time = time {
let calendar = NSCalendar.currentCalendar()
let timeComponents = calendar.components(.HourCalendarUnit | .MinuteCalendarUnit | .TimeZoneCalendarUnit, fromDate: time)
var dateComponents = calendar.components(.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit, fromDate: date)
dateComponents.hour = timeComponents.hour
dateComponents.minute = timeComponents.minute
dateComponents.second = 0
dateComponents.timeZone = timeComponents.timeZone
if let dateFromComponents = calendar.dateFromComponents(dateComponents) {
combinedDate = dateFromComponents
}
}
}
self.init(timeInterval:0, sinceDate: combinedDate)
}
Basically it composes a date from components from two dates. For instance, it takes hours, minutes and seconds from the second NSDate called time, and year, month, and day from the first NSDate called date.
You can modify the components to make more or less accurate. You even extend the intializer to include customized units for the calendar.
Used this code
+ (NSDate *)combineDate:(NSDate *)date withTime:(NSDate *)time
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned unitFlagsDate = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *dateComponents = [gregorian components:unitFlagsDate fromDate:date];
unsigned unitFlagsTime = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *timeComponents = [gregorian components:unitFlagsTime fromDate:time];
[dateComponents setSecond:[timeComponents second]];
[dateComponents setHour:[timeComponents hour]];
[dateComponents setMinute:[timeComponents minute]];
NSDate *combDate = [gregorian dateFromComponents:dateComponents];
return combDate;
}
may help you
Swift 5 version:
init?(date: Date, time: Date) {
let calendar = Calendar.current
let timeComponents = calendar.dateComponents([.hour, .minute, .timeZone], from: time)
var dateComponents = calendar.dateComponents([.year, .month, .day], from: date)
dateComponents.hour = timeComponents.hour
dateComponents.minute = timeComponents.minute
dateComponents.second = 0
dateComponents.timeZone = timeComponents.timeZone
guard let combined = calendar.date(from: dateComponents) else { return nil }
self = combined
}
Assuming you have two strings:
NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
[dateformate setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *outputDate = [dateformate dateFromString:[#"2015-09-01" stringByAppendingString:#"08:33:00"]];

How to set UIDatePicker's date's seconds value to 00?

How to always get seconds value "00" for UIDatePicker's date?
Now I am getting value like this format 5:30:45, I need to get this format of time 5:30:00.
How to achieve this?
I used this code it is working fine.
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit ) fromDate:datePicker.date];
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:datePicker.date];
[dateComponents setHour:[timeComponents hour]];
[dateComponents setMinute:[timeComponents minute]];
[dateComponents setSecond:0.0];
NSDate *newDate = [calendar dateFromComponents:dateComponents];
You don't have to juggle with the NSDateComponents or convert the date to a string and back. You just can tell the calendar to set the date to the beginning of the minute (hour/date/week/…)
NSDate *date = self.datePicker.date;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitMinute
startDate:&date
interval:NULL
forDate:date];
//date now is set to the beginning of the minute -> seconds == 00
NSDate *currentDate = [datePicker date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *Str_Seccond=[dateFormatter stringFromDate:currentDate];
In Str_Seccond string you can get the seconds in string format.
Swift 4 version :
let calendar = NSCalendar.current
let components = calendar.dateComponents([.year, .month, .day,
.hour, .minute],
from: yourDate)
let date = calendar.date(from: components)
NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
[dateformatter setDateFormat:#"ss"];
NSLog(#"%#",[dateformatter stringFromDate:[datePicker date]]);
In Swift:
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month, .Day, .Hour, .Minute], fromDate: datePicker.date)
let date = calendar.dateFromComponents(components)

dynamically create date for previous sunday at 12:00 AM

I'm struggling to figure out how to dynamically create a date object for the most previous sunday at 12:00 AM
I was thinking I could get today's date and then subtract the current day of the week + 1 at which point I could just subtract the time of the day do get down to 12AM.
so far I have the current day of the week:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
int weekday = [comps weekday];
at which point I can get today's date and subtract the difference of weekday * seconds in a day. However, how can I get today's time in seconds ??
No need to manually calculate seconds (which is dangerous anyway because of daylight saving etc.). The following should do exactly what you want:
NSDate *today = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en-US"]]; // force US locale, because other countries (e.g. the rest of the world) might use different weekday numbering
NSDateComponents *nowComponents = [calendar components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:today];
[nowComponents setWeekday:1]; //Sunday
[nowComponents setHour:0]; // 12:00 AM = midnight (12:00 PM would be 12)
[nowComponents setMinute:0];
[nowComponents setSecond:0];
NSDate *previousSunday = [calendar dateFromComponents:nowComponents];
I'll leave worrying about transitions between daylight savings time to you:
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [NSDate date];
NSLog(#"date %#", date);
NSDateComponents *componentsToday = [gregorian components:NSWeekdayCalendarUnit fromDate:date]; // NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
NSInteger days = componentsToday.weekday - 1;
NSLog(#"Days=%d", days);
NSDate *lastSunday = [date dateByAddingTimeInterval:-days*60*60*24];
NSLog(#"lastSunday %#", lastSunday);
NSDateComponents *componentsSunday = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:lastSunday];
[componentsSunday setHour:0];
[componentsSunday setMinute:0];
[componentsSunday setSecond:0];
NSDate *targetDate = [gregorian dateFromComponents:componentsSunday];
NSLog(#"TargetDate %#", targetDate);
#AndreasLey solution in Swift 2.0:
func getLastSunday() -> NSDate?
{
let today = NSDate();
let calendar : NSCalendar! = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
calendar.locale = NSLocale(localeIdentifier: "en-US") // force US locale, because other countries (e.g. the rest of the world) might use different weekday numbering
let flags : NSCalendarUnit = [.Year , .Month, .Weekday, .WeekOfMonth, .Minute , .Second]
let nowComponents = calendar.components(flags, fromDate: today)
nowComponents.weekday = 1 //Sunday
nowComponents.hour = 0 // 12:00 AM = midnight (12:00 PM would be 12)
nowComponents.minute = 0
nowComponents.second = 0;
let previousSunday = calendar.dateFromComponents(nowComponents);
return previousSunday
}
This code is setting 12:00 am in your selected date from UIDatePicker.
NSDate *oldDateSelected = datePicker.date;
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:unitFlags fromDate:oldDateSelected];
comps.hour = 00;
comps.minute = 00;
comps.second = 44;
NSDate *newDate = [calendar dateFromComponents:comps];
return newDate;

Get next year from the current NSDate?

I have a calendar application in which I want to get the next year from the current date (NSDate).
How can I do this?
You can make NSDateComponents do all the hard work of calculating leap years and leap seconds:
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setYear:1];
NSDate *nextYear = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
As VdesmedT mentioned, you can use dateByAddingTimeInterval and add the seconds of one year. But to be more precise, you can do the following:
NSDate *today = [NSDate date]; // get the current date
NSCalendar* cal = [NSCalendar currentCalendar]; // get current calender
NSDateComponents* dateOnlyToday = [cal components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit ) fromDate:today];
[dateOnlyToday setYear:([dateOnlyToday year] + 1)];
NSDate *nextYear = [cal dateFromComponents:dateOnlyToday];
Hope this helps.
Swift 4:
let calendar = Calendar.current
let newDate = calendar.date(byAdding: .year, value: 1, to: Date())
This is my version: in swift.
let calendar = NSCalendar.currentCalendar()
let newDate = calendar.dateByAddingUnit(.Year, value: 1, toDate: NSDate(), options: NSCalendarOptions.MatchNextTime)

Resources