(Obj-c)从日期字符串中识别早晨,下午或晚上

时间:2015-10-17 17:04:37

标签: ios objective-c

我在Objective-C工作。我在字符串中有这三个值,它们决定了当天的部分

NSString *morning = @"7:01";
NSString *afternoon = @"12:01"
NSString *night = @"19:01"

我的原始日期是这个,也是字符串

NSString *currentTime = @"Sat, 17 Oct 2015 9:58 am CDT"

我需要确定当前日期是早上,下午还是晚上,根据当前日期为String。有人有解决方案吗?

2 个答案:

答案 0 :(得分:2)

你的问题得分为负(在撰写本文时为-4),因为人们显然觉得你没有表现出所期望的努力。然而,你的问题隐藏了苹果最近变得更难的问题,这让它变得有趣。

您的抽样时间是:

NSString *currentTime = @"Sat, 17 Oct 2015 9:58 am CDT"

这似乎是"早上"。然而,这与:

完全相同
Sat, 17 Oct 2015 2:58 pm GMT

这似乎是"下午"。这两次都是:

Sat, 17 Oct 2015 14:58 UTC

为什么这是一个问题?

NSDate没有任何关联时区的时间点。类NSDateFormatter以及NSDate本身的关联方法将解析日期时间字符串并生成字符串表示的绝对UTC时间点。字符串中的任何时区(例如示例中的CDT)都允许用于确定绝对时间点,但不会直接表示在NSDate值中。

NSCalendar类用于分解日期的某些部分时,它与时区相关,默认为系统时区。

如果你的应用程序在英国的计算机上运行,​​并且你遵循评论中的建议,那么所有这些加起来就是:

  1. 解析时间(使用NSDateFormatter
  2. 打破时间& min获取NSDateComponents值(使用NSCalendar);和
  3. 比较小时和时间最小化您的边界,然后您的采样时间将报告为"下午"
  4. 不好: - (

    您需要的是解析日期时间(获取标准UTC时间点)时区,然后您可以将该时区传递给NSCalendar,其余的是容易。

    Apple让它变得更难

    OS X 10.9& iOS 7 NSDateFormatter类返回了NSCalendarDate日期值,该类型是NSDate的子类,并且还存储了NSTimeZone值。因此,解析您的样本返回时间点"星期六,2015年10月17日14:58 UTC"和时区" UTC-5"。有了这些信息NSCalendar可以用来打破时间和时间。 min并且正确地确定时间是"早晨"。

    NSCalendarDate现已弃用,虽然仍有可能使用它,但这可能随时发生变化。 Apple似乎还没有提供另一种解析日期和时区"方法

    解析日期和时区偏移量

    从简单的观察,如果你解析"星期六,2015年10月17日上午9:58 CDT"忽略时区并将其视为UTC时,结果是一个绝对时间点,相差5小时,即CDT的时区偏移,如果解析字符串时考虑到时区,则有一个方法可以获得时区 - 解析字符串两次,一旦忽略时区,并确定差异。

    这可能不是最好的算法,但确实有效......(您可以在这里插入有关过早优化的警告!)

    所以这里(最小的评论,查看文档中的方法,错误检查等等 - 仅作为大纲处理):

    - (BOOL) dateAndZoneFromString:(NSString *)timeString // the date-time string
                        dateFormat:(NSString *)dateFormat // the format of the date-time, should contain a time zone format at the end
                        parsedDate:(NSDate **)date        // NSDate representing the absolute time point
                        parsedZone:(NSTimeZone **)zone    // NSTimeZone representing the time zone of the original string
                             error:(NSError **)error
    {
       NSDateFormatter *df = [NSDateFormatter new];
    
       // parse timeString taking time zone into account
       df.dateFormat = dateFormat;
       NSDate *absDate = [df dateFromString:timeString];
    
       // parse timeString ignoring the time zone by removing the format specifier from dateFormat
       df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
       df.dateFormat = [dateFormat stringByReplacingOccurrencesOfString:@" *[zZvV]+$" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, dateFormat.length)];
    
       NSDate *zonelessDate;
       NSRange range = NSMakeRange(0, timeString.length);
       if ( [df getObjectValue:&zonelessDate forString:timeString range:&range error:error] )
       {
          // parse successful, calculate the difference and construct an NSTimeZone value
          NSTimeInterval offset = [zonelessDate timeIntervalSinceDate:absDate];
          NSTimeZone *timezone = [NSTimeZone timeZoneForSecondsFromGMT:offset];
          *date = absDate;
          *zone = timezone;
          return YES;
       }
       else
          return NO;
    }
    

    如果您将@"Sat, 17 Oct 2015 9:58 am CDT"和格式@"E, d MMM y h:m a z"传递给此方法,则会返回时间点"星期六,2015年10月17日14:58 UTC"作为NSDate和时区" UTC-5"作为NSTimeZone

    如果您通过@"Sat, 17 Oct 2015 2:58 pm GMT",则会返回相同的绝对时间点和" UTC + 0"的时区。

    在这一点上,您可以将这些值与NSCalendarNSDateComponents和简单比较结合使用,以确定上午/下午/晚上。

    HTH

答案 1 :(得分:1)

-(void)ShowTimeMessage
{
    // For calculating the current date
    NSDate *date = [NSDate date];

    // Make Date Formatter
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"hh a EEEE"];

    // hh for hour mm for minutes and a will show you AM or PM
    NSString *str = [dateFormatter stringFromDate:date];
    // NSLog(@"%@", str);

    // Sperate str by space i.e. you will get time and AM/PM at index 0 and 1 respectively
    NSArray *array = [str componentsSeparatedByString:@" "];

    // Now you can check it by 12. If < 12 means Its morning > 12 means its evening or night

    NSString *message;
    NSString *timeInHour;
    NSString *am_pm;

    NSString *DayOfWeek;
    if (array.count>2)
    {
        // am pm case
        timeInHour = array[0];
        am_pm = array[1];
        DayOfWeek  = array[2];
    }
    else if (array.count>1)
    {
        // 24 hours case
        timeInHour = array[0];
        DayOfWeek = array[1];
    }

    if (am_pm)
    {

        if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<=9 && [am_pm isEqualToString:@"AM"])
        {
            message = [NSString stringWithFormat:@"Morning"];
                    }
        else if (([timeInHour integerValue]>=10 && [timeInHour integerValue]!=12 && [am_pm isEqualToString:@"AM"]) || (([timeInHour integerValue]<4 || [timeInHour integerValue]==12) && [am_pm isEqualToString:@"PM"]))
        {
            message = [NSString stringWithFormat:@"Afternoon"];
                    }
        else if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<=9 && [am_pm isEqualToString:@"PM"])
        {
            message = [NSString stringWithFormat:@"Evening"];

        }
        else if (([timeInHour integerValue]>=10 && [timeInHour integerValue]!=12 && [am_pm isEqualToString:@"PM"]) || (([timeInHour integerValue]<4 || [timeInHour integerValue]==12) && [am_pm isEqualToString:@"AM"]))
        {
            message = [NSString stringWithFormat:@"Night"];
        }

    }
    else
    {
        if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<10)
        {
            message = [NSString stringWithFormat:@"Morning"];

        }
        else if ([timeInHour integerValue]>=10 && [timeInHour integerValue]<16)
        {
            message = [NSString stringWithFormat:@"Afternoon"];

        }
        else if ([timeInHour integerValue]>=16 && [timeInHour integerValue]<22)
        {
            message = [NSString stringWithFormat:@"Evening"];

        }
        else
        {
            message = [NSString stringWithFormat:@"Night"];

        }
    }

    if (DayOfWeek)
    {
        _timeLbl.text=[NSString stringWithFormat:@"%@ %@",DayOfWeek,message];
    }

}