libs-base/Source/NSDateComponentsFormatter.m

550 lines
17 KiB
Objective-C

/**Implementation of class NSDateComponentsFormatter
Copyright (C) 2019 Free Software Foundation, Inc.
Author: Gregory Casamento <greg.casamento@gmail.com>
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