gpt4 book ai didi

ios - 从一天中的几个小时返回打开、关闭或关闭的功能

转载 作者:可可西里 更新时间:2023-11-01 05:04:22 25 4
gpt4 key购买 nike

我有很多小时的营业时间我想确定商店是在 30、29、28、27 分钟内开放、关闭还是关闭……我正在 Xcode/Objectic-C 中执行此操作。现在我必须这样做,让我们说 50 个不同的操作小时。我已经创建了一个执行此操作的函数,但它的效率不是很高,并且涉及很多 if-else 语句。以下是营业时间示例

Monday - Thursday
7:30am - Midnight
Friday
7:30am - 10:00pm
Saturday
9:00am - 10:00pm
Sunday
9:00am - Midnight

这是我的功能以及我如何处理它
-(BOOL) dateAndTime:(NSDate*)date getStartDay:(NSInteger)startDay getStartHour:(NSInteger)startHour getStartMin:(NSInteger)startMin getEndDay:(NSInteger)endDay getEndHour:(NSInteger)endHour getEndMin:(NSInteger)endMin{

NSCalendar *calendar = [NSCalendar currentCalendar];


const NSCalendarUnit units = NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit;
NSDateComponents *comps = [calendar components:units fromDate:date];

if (comps.weekday == 1) {
comps.weekday = 7;
}
else comps.weekday = comps.weekday - 2;

NSDate *startOfToday;
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startOfToday interval:NULL forDate:date];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone localTimeZone];
[dateFormatter setDateFormat:@"HH:mm"];
[dateFormatter setTimeZone:timeZone];


NSString *dateString = [dateFormatter stringFromDate:date];

NSDate *startDate = [dateFormatter dateFromString:[NSString stringWithFormat:@"%ld:%ld", (long)startHour, (long)startMin]];
NSDate *endDate = [dateFormatter dateFromString:[NSString stringWithFormat:@"%ld:%ld", (long)endHour, (long)endMin]];

NSString *startDateString = [dateFormatter stringFromDate:startDate];
NSString *endDateString = [dateFormatter stringFromDate:endDate];


if ([startDateString compare:dateString] == NSOrderedAscending && [dateString compare:endDateString] == NSOrderedAscending && startDay <= comps.weekday && comps.weekday <= endDay) {
return YES;
}
else return NO;

}

现在我通过一天,从 0-6(0 是星期一)然后是 24 小时制的时间。然后像这样使用它:
    if ([self dateAndTime:date getStartDay:0 getStartHour:7 getStartMin:30 getEndDay:3 getEndHour:23 getEndMin:30] == YES)
text = @"Open";

else if ([self dateAndTime:date getStartDay:0 getStartHour:23 getStartMin:30 getEndDay:3 getEndHour:24 getEndMin:0] == YES)
text = [NSString stringWithFormat:@"Closes in %@ min", countdownNumber];
else text = @"Closed";

正如您所看到的,在一周中的所有天数和每天的小时数中执行此操作需要大量的 if 语句并且非常糟糕。就这个例子而言,它需要 8 个 if-else 语句(非常耗时)

现在这个问题的基础是我怎样才能提高效率/什么是更好的方法来做到这一点,同时还能倒计时最后 30 分钟?

我做了一些研究,但找不到任何可以倒计时的东西,它什么时候关闭并且是有效的。

如果您需要或想查看 https://gist.github.com/spennyf/b0b18e31c3e9deaa0455,这里是示例的完整 if-else 语句

感谢您提前提供帮助和/或建议:)

编辑

这是在我的 .m 文件的顶部我有这个
@interface HomeTableViewController () {

ShopHours WeekSchedule[];
}

@end

但这给了我我在评论中谈到的编译错误,我如何设置这个变量以便它可以在这个 .m 文件中使用?现在我只是通过它作为功能的额外护栏,应该没问题。 :)

一旦我确定它是开放的,如果这个地方在 30 分钟内关闭,那么设置 if 语句的最佳方法是什么?如果一个地方在一天的部分时间/午夜开放,您能否添加设置。

感谢你的帮助 :)

最佳答案

将时间存储为 C 结构会造成许多内存管理问题。如果可以(我认为可以),我会避免这种情况。相反,我建议创建一些新类来帮助我们解决这个问题。

首先,我们应该将这些时间视为“一周内的名义时间”。通过设置这些标称时间,我们可以明确地摆脱 DST 问题,说“周日凌晨 1:30”意味着“我们将称之为凌晨 1:30 的第一个时刻,无论发生什么 DST 转换可能会创建另一个 1:30a .”无论如何,这就是商店通常的工作方式,但在考虑时间函数时要准确很重要。

“一周内的名义时间”的伟大之处在于,我们可以从周日午夜开始计算分钟,并且我们知道一周中正好有 60*24*7(10,080)分钟。我们在这里只关心分钟,所以我们只需要跟踪 0 到 10,079 之间的数字。但我们必须记住,这些数字服从于模算术(它们“环绕”)。问星期二是在星期三之前还是之后是没有意义的。周二是周三之前和之后。但询问星期二是否介于星期一(作为起点)和星期三(作为终点)之间是有意义的。我们可以确定从周二开始我们是否会在遇到星期一之前遇到星期三。如果这是真的,那就是介于两者之间。这就是您必须考虑模块化时间的方式。

好吧,理论太多了。让我们看一些代码(所有代码都是 here )。首先,我们想要一个 WeekTime 来表示一周内的某个时间:

typedef enum {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
} Weekday;

@interface WeekTime : NSObject
@property (nonatomic, readonly) NSInteger minutesSinceStartOfWeek;

- (instancetype)initWithWeekday:(Weekday)weekday hour:(NSInteger)hour minute:(NSInteger)minute;
@end

这个的实现应该是显而易见的,所以我不会在这里粘贴它。

现在我们要考虑名义周时间的范围。我们将制作这些开放范围,因此它们包括开始时间但不包括结束时间。如果某个地点在 9p 关闭,您希望在 9p 返回“Closed”,而不是“Closing in 1m”。
@interface WeekTimeRange : NSObject
@property (nonatomic, readonly) WeekTime *start;
@property (nonatomic, readonly) WeekTime *end;

- (instancetype)initWithStart:(WeekTime *)start end:(WeekTime *)end;
- (BOOL)contains:(WeekTime *)time;
@end

其中大部分应该是显而易见的,但是 contains: 有一个小技巧。由于我们采用模算术,因此 startend “更大”是合法的(记住“更大”并不意味着什么)。这很容易处理:
- (BOOL)contains:(WeekTime *)time {
NSInteger queryMinutes = time.minutesSinceStartOfWeek;
NSInteger startMinutes = self.start.minutesSinceStartOfWeek;
NSInteger endMinutes = self.end.minutesSinceStartOfWeek;

if (startMinutes < endMinutes) {
return (startMinutes <= queryMinutes &&
queryMinutes < endMinutes);
} else {
return (queryMinutes < endMinutes ||
queryMinutes >= startMinutes);
}
}

(在我的示例中,我选择使 start==end 的范围未定义。如果您想为其分配一些含义,即“所有时间”或“没有时间”,那么您可能需要调整它。小心但是,“所有时间”。这真的意味着商店关闭并立即重新营业,因此您会收到“关闭...”消息。这就是我刚刚使 start==end 未定义的原因。)

好的,最后我们需要一些助手:
WeekTimeRange *WTMakeRange(Weekday startDay, NSInteger startHour, NSInteger startMinute,
Weekday endDay, NSInteger endHour, NSInteger endMinute) {
return [[WeekTimeRange alloc]
initWithStart:[[WeekTime alloc] initWithWeekday:startDay hour:startHour minute:startMinute]
end:[[WeekTime alloc] initWithWeekday:endDay hour:endHour minute:endMinute]];
}

WeekTimeRange *WTFindOpenRangeIncluding(NSArray *ranges, WeekTime *time) {
for (WeekTimeRange *range in ranges) {
if ([range contains:time]) {
return range;
}
}
return nil;
}

NSString *WTStatus(WeekTimeRange *range, WeekTime *requestedTime) {
if (range != nil) {
NSInteger minutesLeft = range.end.minutesSinceStartOfWeek - requestedTime.minutesSinceStartOfWeek;
if (minutesLeft < 0) {
minutesLeft += [WeekTime maxMinute];
}
if (minutesLeft <= 30) {
return [NSString stringWithFormat:@"Closing in %ld minutes", (long)minutesLeft];
} else {
return @"Open";
}
} else {
return @"Closed";
}
}

这些应该不需要太多解释。让我们在实践中看到它。您似乎已经知道如何将日期转换为它们的组件,所以我将直接创建一个 WeekTime 而不用担心将它从 NSDate 转换。
    NSArray *shopHours = @[WTMakeRange(Monday, 7, 30, Tuesday, 0, 0),
WTMakeRange(Tuesday, 7, 30, Wednesday, 0, 0),
WTMakeRange(Wednesday, 7, 30, Thursday, 0, 0),
WTMakeRange(Thursday, 7, 30, Friday, 0, 0),
WTMakeRange(Friday, 7, 30, Friday, 22, 0),
WTMakeRange(Saturday, 9, 0, Saturday, 22, 0),
WTMakeRange(Sunday, 9, 0, Monday, 2, 0)
];

WeekTime *mondayElevenPM = [[WeekTime alloc] initWithWeekday:Monday hour:23 minute:00];
WeekTimeRange *openRange = WTFindOpenRangeIncluding(shopHours, mondayElevenPM);
NSString *result = WTStatus(openRange, mondayElevenPM);
NSLog(@"%@", result);

我没有尝试过大量的测试用例,但我的临时测试似乎有效。所有代码都在 gist 中。我不测试的一种情况是您的范围是否重叠。上述算法并不关心范围是否有序,但如果范围重叠,您可能会收到不正确的“关闭...”消息。解决这个问题(通过抛出错误或合并范围)应该是一个非常简单的增强。

关于ios - 从一天中的几个小时返回打开、关闭或关闭的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27631882/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com