Constructing an NSDate from today's date and a

2020-02-13 03:30发布

问题:

If I have a string representing a time, say "10:45 am", and do the following to parse the string:

NSDateFormatter *dateFormat;
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"h:mm a"];
NSLog(@"%@", [dateFormat dateFromString:@"10:45 AM"]);

I would get this logged:

2013-09-09 17:52:30.416 TimeTest[49491:a0b] 2000-01-01 15:45:00 +0000

How can I create an NSDate for the current day at the given time? I tried this

NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"h:mm a"];
NSDate *time = [formatter dateFromString:@"10:45 AM"];
NSDateComponents *timeComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit ) fromDate:time];
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];
NSDateComponents *newComponents = [[NSDateComponents alloc]init];
newComponents.timeZone = [NSTimeZone systemTimeZone];
[newComponents setDay:[dateComponents year]];
[newComponents setMonth:[dateComponents month]];
[newComponents setYear:[dateComponents year]];
[newComponents setHour:[timeComponents hour]];
[newComponents setMinute:[timeComponents minute]];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *combinedDate = [gregorianCalendar dateFromComponents:newComponents];
NSLog(@"%@", combinedDate);

with the result

2013-09-09 19:57:14.506 TimeTest[49712:a0b] 2019-03-06 15:45:00 +0000

How should I go about this?

回答1:

I'm not exactly sure what you are looking for. For what I understand, you want to build a date with the current year, month and day, but with your supplied time by parsing it from a string. If that is the case, as others have pointed out, you need to play with NSDateComponents.

Based on your code I wrote these lines. They should build a date by merging two dates. The current one and the one you parsed.

// Get the full current date
NSDate *date = [NSDate date];

// Get the current calendar
NSCalendar *calendar = [NSCalendar currentCalendar];

// Split the date into components but only take the year, month and day and leave the rest behind
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];

// Build the date formatter
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"h:mm a"];

// Convert the string time into an NSDate
NSDate *time = [formatter dateFromString:@"10:45 AM"];

// Split this one in components as well but take the time part this time
NSDateComponents *timeComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit ) fromDate:time];

// Do some merging between the two date components
dateComponents.hour = timeComponents.hour;
dateComponents.minute = timeComponents.minute;

// Extract the NSDate object again
NSDate *result = [calendar dateFromComponents:dateComponents];

// Check if this was what you where looking for
NSLog(@"%@",result);

Please be aware that this sample code is by far non-optimized. There are more crisp ways to obtain what you are looking for by using time intervals, but I felt like you wanted a dirty simple example on how to do components copy and paste and then extracting dates.



回答2:

This will create a date for the beginning of the day in the current time zone.

NSDate *today = [NSDate date];
NSTimeInterval interval;
NSCalendar *cal = [NSCalendar currentCalendar];
[cal rangeOfUnit:NSDayCalendarUnit
       startDate:&today
        interval:&interval
         forDate:today];

Now we add the time:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// I have to set the locale to posix_en_us, as my system is using 24hour style as default
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setDateFormat:@"hh:mm a"];
NSDate *time = [dateFormatter dateFromString:@"10:45 AM"];
NSDateComponents *comps = [cal components:(NSHourCalendarUnit | NSMinuteCalendarUnit)
                                 fromDate:time];
NSDate *dateAndTime = [cal dateByAddingComponents:comps
                                           toDate:today
                                          options:0];

dateAndTime will now be todays date with 10:45 am in the local timezone.

controlling in the debugger:

po dateAndTime
$0 = 0x41b7df138c00000d 2013-09-10 08:45:00 +0000

This is correct, as my timezone is 2 hours ahead to GMT, as we still have summer time.