/**Implementation of class NSDateComponentsFormatter Copyright (C) 2019 Free Software Foundation, Inc. Author: Gregory Casamento Date: Wed Nov 6 00:24:02 EST 2019 This file is part of the GNUstep Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. */ #import "Foundation/NSDateComponentsFormatter.h" #import "Foundation/NSDate.h" #import "Foundation/NSString.h" #import "Foundation/NSValue.h" #import "Foundation/NSException.h" #import "Foundation/NSNumberFormatter.h" @implementation NSDateComponentsFormatter - (instancetype) init { self = [super init]; if (self != nil) { _calendar = nil; _referenceDate = nil; _allowsFractionalUnits = NO; _collapsesLargestUnit = NO; _includesApproximationPhrase = NO; _formattingContext = NSFormattingContextUnknown; _maximumUnitCount = 0; _zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDefault; _allowedUnits = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; _unitsStyle = NSDateComponentsFormatterUnitsStylePositional; } return self; } - (instancetype) initWithCoder: (NSCoder *)coder { self = [super initWithCoder: coder]; if (self != nil) { // TODO: Implement coding... } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [super encodeWithCoder: coder]; // TODO: Implement coding... } - (void) dealloc { RELEASE(_calendar); RELEASE(_referenceDate); [super dealloc]; } - (NSString *) stringForObjectValue: (id)obj { NSString *result = nil; if ([obj isKindOfClass: [NSDateComponents class]]) { result = [self stringFromDateComponents: obj]; } else if ([obj isKindOfClass: [NSNumber class]]) { NSTimeInterval ti = [obj longLongValue]; result = [self stringFromTimeInterval: ti]; } return result; } - (NSString *) stringFromDateComponents: (NSDateComponents *)components { NSString *result = @""; if (_allowedUnits & NSCalendarUnitYear) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components year]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" years"]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%4ld", (long)[components year]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" yr "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" yr "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" yr "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" years "]; } } } if (_allowedUnits & NSCalendarUnitMonth) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components month]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" months "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%2ld", (long)[components month]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" mn "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" mon "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" months "]; } } } if (_allowedUnits & NSCalendarUnitDay) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components day]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" days "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%2ld", (long)[components day]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" d "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" day "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" days "]; } } } if (_allowedUnits & NSCalendarUnitHour) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components hour]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" hours "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%2ld", (long)[components hour]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" h "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" hrs "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" hours "]; } } } if (_allowedUnits & NSCalendarUnitMinute) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components minute]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" minutes "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%2ld", (long)[components minute]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" min "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" mins "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" minutes "]; } } } if (_allowedUnits & NSCalendarUnitSecond) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; NSNumber *num = [NSNumber numberWithInteger: [components second]]; AUTORELEASE(fmt); [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" seconds "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { NSString *s; s = [NSString stringWithFormat: @"%2ld", (long)[components second]]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" s "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" secs "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" seconds "]; } } } if (_allowedUnits & NSCalendarUnitWeekOfMonth) { if (_unitsStyle == NSDateComponentsFormatterUnitsStyleSpellOut) { NSNumberFormatter *fmt; NSNumber *num; fmt = AUTORELEASE([[NSNumberFormatter alloc] init]); num = [NSNumber numberWithInteger: [components weekOfMonth]]; [fmt setNumberStyle: NSNumberFormatterSpellOutStyle]; result = [result stringByAppendingString: [fmt stringFromNumber: num]]; result = [result stringByAppendingString: @" days "]; } else { if (_zeroFormattingBehavior & NSDateComponentsFormatterZeroFormattingBehaviorDefault) { long wom = (long)[components weekOfMonth]; NSString *s = [NSString stringWithFormat: @"%2ld", wom]; result = [result stringByAppendingString: s]; } if (_unitsStyle == NSDateComponentsFormatterUnitsStylePositional) { result = [result stringByAppendingString: @" "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleAbbreviated) { result = [result stringByAppendingString: @" wm "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleShort) { result = [result stringByAppendingString: @" wom "]; } else if (_unitsStyle == NSDateComponentsFormatterUnitsStyleFull) { result = [result stringByAppendingString: @" week of month "]; } } } return result; } - (NSString *) stringFromDate: (NSDate *)startDate toDate: (NSDate *)endDate { NSDateComponents *dc; NSCalendar *calendar; calendar = ( _calendar != nil ) ? _calendar : [NSCalendar currentCalendar]; dc = [calendar components: _allowedUnits fromDate: startDate toDate: endDate options: NSCalendarMatchStrictly]; return [self stringFromDateComponents: dc]; } - (NSString *) stringFromTimeInterval: (NSTimeInterval)ti { NSDate *startDate = [NSDate date]; NSDate *endDate = [startDate dateByAddingTimeInterval: (ti > 0) ? ti : -ti]; return [self stringFromDate: startDate toDate: endDate]; } - (NSDateComponentsFormatterUnitsStyle) unitsStyle { return _unitsStyle; } - (void) setUnitsStyle: (NSDateComponentsFormatterUnitsStyle)style { _unitsStyle = style; } - (NSCalendarUnit) allowedUnits { return _allowedUnits; } - (void) setAllowedUnits: (NSCalendarUnit)units { if (units & NSCalendarUnitYear && units & NSCalendarUnitMonth && units & NSCalendarUnitDay && units & NSCalendarUnitHour && units & NSCalendarUnitMinute && units & NSCalendarUnitSecond && units & NSCalendarUnitWeekOfMonth) { [NSException raise: NSInvalidArgumentException format: @"Passed invalid unit into allowedUnits"]; } _allowedUnits = units; } - (NSDateComponentsFormatterZeroFormattingBehavior) zeroFormattingBehavior { return _zeroFormattingBehavior; } - (void) setZeroFormattingBehavior: (NSDateComponentsFormatterZeroFormattingBehavior)behavior { _zeroFormattingBehavior = behavior; } - (NSCalendar *) calendar { return _calendar; } - (void) setCalender: (NSCalendar *)calendar { ASSIGNCOPY(_calendar, calendar); } - (NSDate *) referenceDate { return _referenceDate; } - (void) setReferenceDate: (NSDate *)referenceDate { ASSIGNCOPY(_referenceDate, referenceDate); } - (BOOL) allowsFractionalUnits { return _allowsFractionalUnits; } - (void) setAllowsFractionalUnits: (BOOL)allowsFractionalUnits { _allowsFractionalUnits = allowsFractionalUnits; } - (NSInteger) maximumUnitCount { return _maximumUnitCount; } - (void) setMaximumUnitCount: (NSInteger)maximumUnitCount { _maximumUnitCount = maximumUnitCount; } - (BOOL) collapsesLargestUnit { return _collapsesLargestUnit; } - (void) setCollapsesLargestUnit: (BOOL)collapsesLargestUnit { _collapsesLargestUnit = collapsesLargestUnit; } - (BOOL) includesApproximationPhrase { return _includesApproximationPhrase; } - (void) setIncludesApproximationPhrase: (BOOL)includesApproximationPhrase { _includesApproximationPhrase = includesApproximationPhrase; } - (NSFormattingContext) formattingContext { return _formattingContext; } - (void) setFormattingContext: (NSFormattingContext)formattingContext { _formattingContext = formattingContext; } - (BOOL) getObjectValue: (id*)obj forString: (NSString *)string errorDescription: (NSString **)error { return NO; } + (NSString *) localizedStringFromDateComponents: (NSDateComponents *)components unitsStyle: (NSDateComponentsFormatterUnitsStyle)unitsStyle { NSDateComponentsFormatter *fmt = [[NSDateComponentsFormatter alloc] init]; [fmt setUnitsStyle: unitsStyle]; AUTORELEASE(fmt); return [fmt stringFromDateComponents: components]; } @end