NSDate: The right way to work with the time of day?

I work with a schedule that indicates the time of day, for example 10:30. However, I do not know the date. I am going to store them as values ​​in NSDictionaryand would like to deal with them in a simple way.

I can’t use NSDate, because I don’t have a date. At least not in the literal sense.

Another way that seems obvious is NSTimeInterval, but it looks like, this is probably the source of very subtle errors. I think, in particular, about daylight saving time (in my opinion, this week for some reason!).

Also, the only thing spring really costs is to keep it in a formatted string or encode it in NSNumber(e.g., hours * 60 + minutes). Of course, both of them will work well, but it seems that I am inventing a square wheel, where I am sure that there is already a round one.

What is the smallest value against a grain-based raw time method with Cocoa?

+3
source share
3 answers

, , , . , (, "22:00" ), , , . , .

, , , , , , NSDate NSDateComponents, NSCalendar -dateFromComponents:.

, , , NSDate, DST, . ( , , , DST)

+2

, , . Cocoa , DST, .

, , , - .

:

//
//  TimeTest.m
//

#import <Foundation/Foundation.h>

#import "Utility.h"

id utility;

void testTime( NSTimeInterval time ) {
    id gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];

    id oneDay = [[[NSDateComponents alloc] init] autorelease];
    [oneDay setDay: 1];

    id thisDay = [gregorian dateFromComponents: [gregorian components: (NSEraCalendarUnit | NSYearCalendarUnit)
                                                             fromDate: [NSDate date]]];
    for (NSInteger dayIdx = 0; dayIdx < 365; ++dayIdx ) {
        NSDate *dateTime = [utility timeInSeconds: time
                                           onDate: thisDay];
        NSLog( @"%@", dateTime );

        thisDay = [gregorian dateByAddingComponents: oneDay
                                             toDate: thisDay
                                            options: 0];
    }
}



int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    utility = [[[Utility alloc] init] autorelease];

    testTime( ((10 * 60.0) + 0.0) * 60.0 );
    testTime( ((9 * 60.0) + 30.0) * 60.0 );

    [pool drain];
    return 0;
}

:

//
//  Utility.h
//

#import <Foundation/Foundation.h>


@interface Utility : NSObject {
    NSCalendar *gregorian;
    NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
}

- (NSDate *)timeInHours: (NSInteger)hours
                minutes: (NSInteger)minutes
                seconds: (NSInteger)seconds
                 onDate: (NSDate *)inDate;

- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
                   onDate: (NSDate *)inDate;

@end

:

//
//  Utility.m
//

#import "Utility.h"


@interface Utility()
@property (nonatomic, readwrite, retain) NSCalendar *gregorian;
@property (nonatomic, readwrite, retain) NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
@end



@implementation Utility



@synthesize gregorian, dateWithoutTimeFormatter, dateWithTimeFormatter;



- (NSDate *)timeInHours: (NSInteger)hours
                minutes: (NSInteger)minutes
                seconds: (NSInteger)seconds
                 onDate: (NSDate *)inDate;
{
    id timeStr = [[NSMutableString alloc] initWithFormat: @"%02d:%02d:%02d", hours, minutes, seconds];
    id dateStr = [dateWithoutTimeFormatter stringFromDate: inDate];
    id dateTimeStr = [[NSString alloc] initWithFormat: @"%@ %@", dateStr, timeStr];
    [timeStr release];
    id dateTime = [dateWithTimeFormatter dateFromString: dateTimeStr];
    [dateTimeStr release];
    return dateTime;
}



- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
                   onDate: (NSDate *)inDate;
{
    NSAssert1( inTime < 24.0 * 3600.0, @"Time %f must be less than 24hrs", inTime );

    double temp = inTime;
    int hours = rintf(floor( temp / 3600.0 ));
    temp -= ( hours * 3600 );
    int minutes = rintf(floorf( temp / 60.0 ));
    temp -= ( minutes * 60 );
    int seconds = rintf( temp );

    return [self timeInHours: hours
                     minutes: minutes
                     seconds: seconds
                      onDate: inDate];
}



- (id)init;
{
    if (( self = [super init] )) {
        self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];
        self.dateWithoutTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [dateWithoutTimeFormatter setDateFormat: @"yyyy-MM-dd"];
        self.dateWithTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [dateWithTimeFormatter setDateFormat: @"yyyy-MM-dd HH:mm:ss"];
    }
    return self;
}



- (void)dealloc;
{
    self.gregorian = nil;
    self.dateWithoutTimeFormatter = nil;
    self.dateWithTimeFormatter = nil;
    [super dealloc];
}



@end

? , , , NSCalendar NSDateFormatter .

+2

You can use NSDateComponentsto store only those components that you need (for example, hours and minutes), and then use NSCalendar dateByAddingComponents:toDate:options:to create an absolute link to the date when you need to use serialized components and a base date.

0
source

Source: https://habr.com/ru/post/1772723/


All Articles