【问题标题】:Check if string is in format dd.mm.yyyy检查字符串是否为 dd.mm.yyyy 格式
【发布时间】:2015-12-28 13:44:37
【问题描述】:

我想检查一个字符串是否是 dd.mm.yyyy 格式,比如

if(myString is in format dd.mm.yyyy) {
  NSLog(@"Ok");
}
else{
  NSLog(@"No");

【问题讨论】:

  • 使用NSDateFormatter。

标签: objective-c string date format


【解决方案1】:

您可以使用这样的代码:

NSString *dateString = @"01.01.1970"; 
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"dd.MM.yyyy";
if ([dateFormatter dateFromString:dateString]) {
    //YES
}

为什么NSDateFormatter:它是为了解析日期而创建的。此外,通过这种方式,您可以轻松更改日期格式,并获得一个可以使用的有效NSDate 对象。

但是,如果您打算经常使用此 dateFormatter(例如,在 UITableViewCell 中使用它),您可能会遇到性能问题。如果你这样做了,并且你确定 NSDateFormatter 是导致它的原因(仪器可能会帮助你),你可以重用你的 dateFormatter。比如像这样:

NSString *dateString = @"01.01.1970"; 
static NSDateFormatter *dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"dd.MM.yyyy";
});

if ([dateFormatter dateFromString:dateString]) {
    //YES
}

似乎(这是我基于我运行的测试的猜测)第一次调用dateFromString 会触发dateFormatter 内部的延迟初始化,这需要一些时间(下面是几个测试结果)。如果重复使用,NSDateFormatter 初始化只会执行一次。

在装有 iOS 8.4.1 的 iPhone 5S 上,dispatch_once 版本的运行速度大约快了 10 倍:

dispatch_once:0.536 秒,娱乐:5.475 秒 (解析 10.000 个日期的时间)

在同一测试中,@zaph 在他的 iPhone 6S 和 iOS 9.x 上获得了 2 倍的性能差异:

dispatch_once:0.57 秒,娱乐:1.01 秒 (解析 10.000 个日期的时间)

因此,这取决于设备、操作系统版本以及您要使用该 dateFormatter 的密集程度。在某些情况下,第二个代码片段可能是多余的。但我遇到了一些情况,它提供了显着的性能提升。

UPD: 另请注意,美国的日期通常也用点作为分隔符,所以看起来是 dd.MM.yyyy 的日期实际上可能是 MM.dd.yyyy 的日期(例如四月5 日而不是 5 月 4 日)。对于dd > 12 的日期,这不是问题,否则就是问题。不过,我认为如果没有额外的上下文,您将无能为力,因此请注意。

【讨论】:

  • 我无法想象为什么有人会否决这个答案。
  • 创建NSDateFormatter 的成本是多少?
  • @zaph,它非常昂贵。这不是你想在cellForRowAtIndexPath 中做的事情。例如(我知道是因为它遇到了令人失望的表现)。我会在一分钟内用一个小演示和一个测试结果更新我的答案。
  • 什么是“显着昂贵”的秒数?
  • Donald Knuth:“过早的优化是编程中万恶(或至少是大部分)的根源”和 Kent Beck:“做最简单的事情可能会奏效”。 Zaph:“不先测量就不要优化。”导致代码失败的是复杂性。
【解决方案2】:

您可以使用正则表达式来检查它。 例如此代码使用正则表达式检查“mm.dd.yyyy”:

NSError *error = NULL;
NSString *expForreg = @"^((((0[13578])|([13578])|(1[02]))[\\.](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\\.](([1-9])|([0-2][0-9])|(30)))|((2|02)[\\.](([1-9])|([0-2][0-9]))))[\\.]\\d{4}$|^\\d{4}$";
NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:expForreg
                              options:NSRegularExpressionCaseInsensitive
                              error:&error];
NSArray *matches = [regex matchesInString:@"10.30.1989" options:0 range:NSMakeRange(0, [@"10.30.1989" length])];
if(matches && matches.count > 0)
{
    NSLog(@"Ok");
}else
{
    NSLog(@"No");
}

希望对您有所帮助!

【讨论】:

  • 为什么不使用NSDateFormatter?那个正则表达式很疯狂。它可以处理闰年吗?
  • @rmaddy:在这种情况下(仅“mm.dd.yyyy”),我认为 NSDateFormatter 是正确的选择。但是,如果你想允许检查 "mm/dd/mmmm", "mm-dd-yyyy",... 尝试使用正则表达式。
  • 嗯?无论日期格式如何,NSDateFormatter 都是正确的选择。这就是它的目的。
  • @Franken,但 OP 想要“dd.mm.yyyy”,而不是“mm.dd.yyyy” :) 还有一个问题:将此正则表达式重写为“dd.mm”的正则表达式.yyyy”(实际上是 MM,不是 mm,但没关系)... 很棘手 :) 尤其是在你写完它半年后。不过,我同意,正则表达式可用于检查日期在多种格式中是否有效。但它会使这个正则表达式更大更可怕,所以如果它适合我​​,我不会使用它:) 此外,你的正则表达式认为02.29.2015 是一个有效日期。这是错误的,因为它不是闰年。正则表达式很棘手:)
  • @Franken,另一方面,0001 是一个“正确”的日期。这是您在可视化调试器中的正则表达式:debuggex link
【解决方案3】:

你可以使用正则表达式:

NSString *testString = @"11.22.3333";

NSString *pattern = @"^\\d{2}\\.\\d{2}\\.\\d{4}$";
NSRange range = [testString rangeOfString:pattern options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
    NSLog(@"Ok");
}
else{
    NSLog(@"No");
}

这不是一个很好的日期测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 2013-02-05
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多