3

我正在使用 NSDateFormatter 来格式化一段时间(见这里)。

我想使用这样的格式:“3 小时 15 分钟”。
这是我正在使用的格式字符串:@"H' hours, 'm' minutes'".

问题是,对于短于一小时的持续时间,结果类似于“0 小时,35 分钟”。
在这种情况下,我只想显示“35 分钟”。

有没有办法告诉 NSDateFormatter 如果没有小时根本不显示时间,还是应该只使用 if 语句并手动构造字符串?

编辑:
我很清楚这很容易通过几行额外的手动完成,这就是我过去的做法。我只是想知道格式化程序是否有足够的智慧来自己处理这个问题,因为这似乎是一个常见问题。

4

6 回答 6

5

从 iOS 8.0 和 Mac OS X 10.10 (Yosemite) 开始,您可以使用NSDateComponentsFormatter. 因此,让我们使用小时和分钟作为allowedUnits(如您的示例)并NSDateComponentsFormatterZeroFormattingBehaviorDropLeading减少zeroFormattingBehavior零小时。例子:

NSTimeInterval intervalWithHours = 11700; // 3:15:00
NSTimeInterval intervalWithZeroHours = 2100; // 0:35:00
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.allowedUnits = NSCalendarUnitHour | NSCalendarUnitMinute;
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropLeading;
NSString *string = [formatter stringFromTimeInterval:intervalWithHours];
NSString *stringWithoutHours = [formatter stringFromTimeInterval:intervalWithZeroHours];
NSLog(@"%@ / %@", string, stringWithoutHours);
// output: 3 hours, 15 minutes / 35 minutes

斯威夫特 5 版本:

let intervalWithHours: TimeInterval = 11700
let intervalWithZeroHours: TimeInterval = 2100
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute]
formatter.unitsStyle = .full
formatter.zeroFormattingBehavior = .dropLeading
if let string = formatter.string(from: intervalWithHours), let stringWithoutHours = formatter.string(from: intervalWithZeroHours) {
    print("\(string) / \(stringWithoutHours)")
    // output: "3 hours, 15 minutes / 35 minutes\n"
}
于 2015-01-21T16:13:55.407 回答
2

一旦你有了日期字符串(我们称之为foo),只需通过发送 stringByReplacingOccurencesOfString:withString: 来创建另一个字符串。例如:

NSString* foo = @"0 hours, 35 minutes";
NSString* bar = [foo stringByReplacingOccurrencesOfString:@"0 hours, " withString:@"" options:0 range:NSMakeRange(0,9)];
NSLog(@"%@",bar);

输出是:

35 minutes

我怀疑这与其他可能的方法相比是否非常有效,但除非您必须对数百个字符串执行此操作,否则它可能并不重要。

编辑:另外,如果您希望能够在没有 0 小时的情况下获得日期,并假设您使用的是 stringFromDate: 您可以添加一个类别来添加这样的方法:

- (NSString *)stringFromDateWithoutZeroHours:(NSDate *)date{
    result = [self stringFromDate:date];
    return [result stringByReplacingOccurrencesOfString:@"0 hours, " withString:@"" options:0 range:NSMakeRange(0,9)];
}
于 2012-09-02T19:51:47.113 回答
1

这是使用 NSCalendar 和 NSDateComponents 的一种方法:

static NSString *stringWithTimeInterval (NSTimeInterval interval)
{
    NSDate *referenceDate = [NSDate dateWithTimeIntervalSince1970:0];
    NSDate *intervalDate = [NSDate dateWithTimeIntervalSince1970:interval];

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:referenceDate toDate:intervalDate options:0];

    NSMutableArray *stringComponents = [NSMutableArray array];

    NSInteger hours = [components hour];
    NSInteger minutes = [components minute];

    if (hours > 0) {
        [stringComponents addObject:[NSString stringWithFormat:@"%ld hours", hours]];
    }
    [stringComponents addObject:[NSString stringWithFormat:@"%ld minutes", minutes]];

    return [stringComponents componentsJoinedByString:@" "];
}
于 2012-09-02T19:52:02.137 回答
1

为什么不为这种情况创建自己的 NSDateFormatter 子类并覆盖stringFromDate(如果这是您所调用的)?

于 2012-09-02T19:36:30.257 回答
0

好的,我要从Rob Mayoff那里窃取一些代码:

他的原文(稍作修改):

-(NSString*) doit:(NSTimeInterval)timeInterval {
    NSUInteger seconds = (NSUInteger)round(timeInterval);
    NSString *result = [NSString stringWithFormat:@"%u hours, %u minutes", seconds / 3600, (seconds / 60) % 60];
    return result;
}

简单的修改以返回有/没有“小时”:

-(NSString*) doit:(NSTimeInterval)timeInterval {
    NSString* result = nil;
    NSUInteger seconds = (NSUInteger)round(timeInterval);
    NSUInteger hours = seconds / 3600;
    NSUInteger minutes = (seconds / 60) % 60;
    if (hours > 0) {
        result = [NSString stringWithFormat:@"%u hours, %u minutes", hours, minutes];
    }
    else {
        result = [NSString stringWithFormat:@"%u minutes", minutes];
    }
    return result;
}

再次,但消除了if

-(NSString*) doit:(NSTimeInterval)timeInterval {
    NSUInteger seconds = (NSUInteger)round(timeInterval);
    NSUInteger hours = seconds / 3600;
    NSUInteger minutes = (seconds / 60) % 60;
    NSString* result = hours ? [NSString stringWithFormat:@"%u hours, %u minutes", hours, minutes] : [NSString stringWithFormat:@"%u minutes", minutes];
    return result;
}

现在,我可以使用 将其归结为一个荒谬的 1-liner ,,但这有点愚蠢,并且不会使代码更清晰。

(请注意,由于 iOS 12/24 “fechure”,所有使用 NSDateFormatter 的方案都被破坏了。)

于 2012-09-03T01:48:36.797 回答
0

根据@matt 的回答,我已经成功地使用他的方法来制作有条件的日期格式。在我的情况下,我只想要该月的第一天,否则就是一天。我需要为 CorePlot 提供一个日期格式化程序以进行轴格式化,并且它必须是有条件的。

@interface MyNSDateFormatter : NSDateFormatter
@property (nonatomic) NSDateFormatter *dateFormatterFirstDay;
@property (nonatomic) NSDateFormatter *dateFormatterTheRest;
@end

@implementation MyNSDateFormatter
-(id)init
{
    self = [super init];
    if(self != nil)
        {
        _dateFormatterFirstDay = [[NSDateFormatter alloc] init];
        _dateFormatterTheRest = [[NSDateFormatter alloc] init];

        [_dateFormatterFirstDay setDateFormat:@"MMM"];
        [_dateFormatterTheRest setDateFormat:@"d"];
    }
    return self;
}

-(NSString *)stringFromDate:(NSDate *)date
{
    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:date];
    if ([dateComponents day] == 1) return [_dateFormatterFirstDay stringFromDate:date];
    else return [_dateFormatterTheRest stringFromDate:date];
}
@end
于 2013-10-10T12:16:30.283 回答