【问题标题】:Get an NSDate for a following day of week from a reference NSDate?从参考 NSDate 获取一周中下一天的 NSDate?
【发布时间】:2012-11-02 11:01:46
【问题描述】:

给定一个参考日期,我需要找到下面的“星期三”。

要明确一点,如果参考日期是星期二,那么它应该返回 同一周的星期三。

如果参考日期是星期三或更晚,则需要从下一个周返回下一个星期三。

重要的是它不会返回参考日期之后的星期三。

我一直在考虑使用 NSDateComponents,但不知道如何获得一周中的第二天,它必须总是在未来。

这是我目前所拥有的:

NSDate *referenceDate = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:referenceDate];
[dateComponents setWeekday:4]; // Wednesday
NSDate *followingWednesday = [calendar dateFromComponents:dateComponents];

虽然这段代码没有区分同一周过去的星期三或下一个星期三,但我的问题是谎言。

我知道我可以生成两个日期,一个来自本周,一个来自下周,然后使用 if 语句检查哪个是未来,但这似乎需要很多代码来做一件简单的事情。

有没有更好的办法?

任何帮助将不胜感激。


更新

似乎设置工作日实际上并不影响NSCalendar的dateComponents:方法返回的日期。无论工作日设置什么,我上面的示例代码都会返回相同的日期。

所以现在我更难过了。

【问题讨论】:

  • 如果日期是过去的,加 7 天怎么样,否则不要管它?
  • 是的,这基本上就是我正在做的事情,但我很想知道他们是否是一种更好的方式来表达“下周三找我”,而无需编写大量额外的逻辑。我希望关于 NSDateComponents 类有一些我错过的东西。可能没有,那很好,我会按照我现在的方式去做。

标签: objective-c ios date nsdate nsdatecomponents


【解决方案1】:

我会这样做:

NSDate *referenceDate = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit) fromDate:referenceDate];

int targetWeekday = 4;

if (dateComponents.weekday >= targetWeekday)
{
    dateComponents.week++;
}

dateComponents.weekday = targetWeekday;
NSDate *followingTargetDay = [calendar dateFromComponents:dateComponents];

【讨论】:

  • 您在向日历询问组件时是否添加了NSWeekdayCalendarUnitNSWeekCalendarUnit 标志?您可能还必须删除 NSDayCalendarUnit 标志。我现在无法测试它。
  • 当场,我不得不删除NSDayCalendarUnit。谢谢!
【解决方案2】:

您必须通过 NSDateFormatter。你可以做这样的事情来计算下一个星期三。我不确定你想要什么,但这里有一个例子:

NSDate *referenceDate = [NSDate date];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *mincomp = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:referenceDate];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"e"];
while ([[formatter stringFromDate:[cal dateFromComponents:mincomp]] intValue] != 4)
    mincomp.day += 1;
[formatter setDateFormat:@"yyyy-MM-dd"];
NSLog(@"next wednesday = %@", [formatter stringFromDate:[cal dateFromComponents:mincomp]]);

【讨论】:

  • 这很有趣,并且确实有效,尽管您不得不依赖NSDateFormatter 来执行此操作似乎很奇怪。使用NSDateFormatter 有什么注意事项吗?
  • 据我所知,没有。
【解决方案3】:

使用dateWithNaturalLanguageString

NSDate *date = [NSDate dateWithNaturalLanguageString:@"next Wednesday"];
NSLog(@"%@",date);

注意dateWithNaturalLanguageString:

创建并返回一个设置为给定字符串指定的日期和时间的 NSDate 对象。

+ (id)dateWithNaturalLanguageString:(NSString *)string

参数

字符串

一个字符串,其中包含一个日期的通俗规范,例如“last Tuesday at Dinner”、“2001 年 12 月 31 日下午 3 点”、“12/31/01”或“31/12/01”。

p>

【讨论】:

  • 很想使用它,不幸的是,这只支持 MacOS X。抱歉应该明确说明我使用的是 iOS 5。请参阅标签。
  • 另外你应该考虑到这适用于优先选择英语的人,这种情况下对于使用 os x 的人来说是一个很好的方法。
  • 我认为这是一种私有 API 方法,因此 Apple 很可能会拒绝使用它。我不能冒这个险。
  • @Prince -- iOS 下没有记录。
  • @Prince -- "没有已知的 dateWithNaturalLanguageString 类选择器"
【解决方案4】:

我没有把整个事情很好地联系起来,因为我昨天巧合地在另一台计算机上完成了实现,但大致如下:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"e"];
NSInteger day = [[formatter stringFromDate:theDate] integerValue];
NSInteger offsetDays = (targetDay - day);  // targetDay is 4 for Wednesday
if (offsetDays < 0) offsetDays += 7;
NSDate* resultDate = [theDate dateByAddingTimeInterval:offsetDays * secondsInADay];

(offsetDays 的计算可能有点乱——这种事情比早上这个时候需要更多的思考。)

【讨论】:

  • 我不确定这个解决方案能否正确处理时区和夏令时。
  • @Camsoft - 无论时区如何,上述内容都应该可以正常工作,因为它甚至会以 24 小时为增量偏移。 (当然,格式化程序需要设置为您关心的 TZ,以便获得正确的日期。)但 DST 更改需要单独的努力。
【解决方案5】:

This guy nailed it.

适用于 OP:

NSDate *refDate = [NSDate date]; // or whatever
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];

NSDateComponents *nowComponents = [gregorian components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:refDate];
int wednesday = 4;
if(nowComponents.weekday >= wednesday) {
    [nowComponents setWeek: nowComponents.week + 1]; // Next week
}
[nowComponents setWeekday:wednesday]; // Wednesday
[nowComponents setHour:8]; // Specific time (if desired)
[nowComponents setMinute:0];
[nowComponents setSecond:0];

NSDate *nextWednesday = [gregorian dateFromComponents:nowComponents];

正如您所说,即使参考日期是星期三,这每次都会得到“下星期三”。

编辑:修正了 cmets 中指出的错误。

【讨论】:

  • 假设 refDate 是星期二,并且您使用此代码:您将获得 8 天后的星期三,而不是 OP 要求的 1 天后的星期三。
  • 呸。很好的捕捉和愚蠢的我。需要有条件地增加一周,就像@Tobi 所做的那样。
猜你喜欢
  • 2012-12-12
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
  • 2017-06-26
相关资源
最近更新 更多