mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Implement -components:fromDate:toDate:options:
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39202 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cf85f75b01
commit
27de2178a1
4 changed files with 144 additions and 0 deletions
|
@ -1,3 +1,12 @@
|
|||
2015-11-30: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
|
||||
* Source/NSCalendar.h
|
||||
* Headers/Foundation/NSCalendar.h:
|
||||
Implement -components:fromDate:toDate:options:. (Not handling
|
||||
NSWrapCalendarComponents yet.)
|
||||
* Tests/base/NSCalendar/component-diff.m:
|
||||
Test case for new functionality.
|
||||
|
||||
2015-11-22 Riccardo Mottola <rm@gnu.org>
|
||||
|
||||
* Source/NSFileManager.m (createDirectoryAtPath)
|
||||
|
|
|
@ -194,6 +194,17 @@ enum
|
|||
|
||||
- (NSDateComponents *) components: (NSUInteger) unitFlags
|
||||
fromDate: (NSDate *) date;
|
||||
/**
|
||||
* Compute the different between the specified components in the two dates.
|
||||
* Values are summed up as long as now higher-granularity unit is specified.
|
||||
* That means if you want to extract the year and the day from two dates
|
||||
* which are 13 months + 1 day apart, you will get 1 as the result for the year
|
||||
* but the rest of the difference in days. (29 <= x <= 32, depending on the
|
||||
* month).
|
||||
*
|
||||
* Please note that the NSWrapCalendarComponents option that should affect the
|
||||
* calculations is not presently supported.
|
||||
*/
|
||||
- (NSDateComponents *) components: (NSUInteger) unitFlags
|
||||
fromDate: (NSDate *) startingDate
|
||||
toDate: (NSDate *) resultDate
|
||||
|
|
|
@ -367,12 +367,81 @@ static NSRecursiveLock *classLock = nil;
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience macro for field extraction.
|
||||
* TODO: We need to implement NSWrapCalendarComponents, but it is unclear how that
|
||||
* actually works.
|
||||
*/
|
||||
#define COMPONENT_DIFF(cal, units, components, toDate, nsunit, setSel, uunit, err) \
|
||||
do { if (units & nsunit) \
|
||||
{ \
|
||||
int32_t uunit ## Diff = ucal_getFieldDifference(cal, toDate, uunit, &err); \
|
||||
if (U_FAILURE(err)) \
|
||||
{ \
|
||||
RELEASE(components); \
|
||||
return nil; \
|
||||
} \
|
||||
[components setSel uunit ## Diff]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
- (NSDateComponents *) components: (NSUInteger) unitFlags
|
||||
fromDate: (NSDate *) startingDate
|
||||
toDate: (NSDate *) resultDate
|
||||
options: (NSUInteger) opts
|
||||
{
|
||||
#if GS_USE_ICU == 1
|
||||
NSDateComponents *comps = nil;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
UDate udateFrom = (UDate)floor([startingDate timeIntervalSince1970] * 1000.0);
|
||||
UDate udateTo = (UDate)floor([resultDate timeIntervalSince1970] * 1000.0);
|
||||
ucal_setMillis (my->cal, udateFrom, &err);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
comps = [[NSDateComponents alloc] init];
|
||||
/*
|
||||
* Since the ICU field difference function automatically advances the calendar as appropriate, we
|
||||
* need to process the units from the largest to the smallest.
|
||||
*/
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSEraCalendarUnit, setEra:, UCAL_ERA, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSYearCalendarUnit, setYear:, UCAL_YEAR, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSMonthCalendarUnit, setMonth:, UCAL_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSWeekOfYearCalendarUnit, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
||||
if (!(unitFlags & NSWeekOfYearCalendarUnit))
|
||||
{
|
||||
/* We must avoid setting the same unit twice (it would be zero because
|
||||
* of the automatic advancement.
|
||||
*/
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSWeekCalendarUnit, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
||||
}
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSWeekOfMonthCalendarUnit, setWeekOfMonth:, UCAL_WEEK_OF_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSDayCalendarUnit, setDay:, UCAL_DAY_OF_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSWeekdayOrdinalCalendarUnit, setWeekdayOrdinal:, UCAL_DAY_OF_WEEK_IN_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSWeekdayCalendarUnit, setWeekday:, UCAL_DAY_OF_WEEK, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSHourCalendarUnit, setHour:, UCAL_HOUR_OF_DAY, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSMinuteCalendarUnit, setMinute:, UCAL_MINUTE, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo, NSSecondCalendarUnit, setSecond:, UCAL_SECOND, err);
|
||||
# if 0
|
||||
if (unitFlags & NSCalendarUnitNanosecond)
|
||||
{
|
||||
int32_t ns = ucal_getFieldDifference(my->cal, udateTo, UCAL_MILLISECOND, &err) * 1000000;
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
RELEASE(comps);
|
||||
return nil;
|
||||
}
|
||||
[comps setNanosecond: ns];
|
||||
}
|
||||
# endif
|
||||
return AUTORELEASE(comps);
|
||||
|
||||
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSDate *) dateByAddingComponents: (NSDateComponents *) comps
|
||||
|
|
55
Tests/base/NSCalendar/component-diff.m
Normal file
55
Tests/base/NSCalendar/component-diff.m
Normal file
|
@ -0,0 +1,55 @@
|
|||
#import "Testing.h"
|
||||
#import "ObjectTesting.h"
|
||||
#import <Foundation/NSCalendar.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
#import <Foundation/NSLocale.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(GS_USE_ICU)
|
||||
#define NSCALENDAR_SUPPORTED GS_USE_ICU
|
||||
#else
|
||||
#define NSCALENDAR_SUPPORTED 1 /* Assume Apple support */
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
NSDateComponents *comps;
|
||||
NSCalendar *cal;
|
||||
NSDate *date;
|
||||
NSDate *date2;
|
||||
|
||||
START_SET("NSCalendar date component differences")
|
||||
if (!NSCALENDAR_SUPPORTED)
|
||||
SKIP("NSCalendar not supported\nThe ICU library was not available when GNUstep-base was built")
|
||||
|
||||
cal = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
|
||||
[cal setFirstWeekday: 1];
|
||||
|
||||
date = [NSDate dateWithString: @"2015-01-01 01:01:01 +0100"];
|
||||
date2 = [NSDate dateWithString: @"2015-02-03 04:05:06 +0100"];
|
||||
|
||||
comps = [cal components: NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
|
||||
| NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
|
||||
fromDate: date
|
||||
toDate: date2
|
||||
options: 0];
|
||||
PASS([comps year] == 0, "year difference correct");
|
||||
PASS([comps month] == 1, "month difference correct");
|
||||
PASS([comps day] == 2, "day difference correct");
|
||||
PASS([comps hour] == 3, "hour difference correct");
|
||||
PASS([comps minute] == 4, "minute difference correct");
|
||||
PASS([comps second] == 5, "second difference correct");
|
||||
|
||||
comps = [cal components: NSDayCalendarUnit
|
||||
fromDate: date
|
||||
toDate: date2
|
||||
options: 0];
|
||||
PASS([comps month] == NSNotFound, "no month returned if not requested");
|
||||
PASS([comps day] == 33, "day difference without larger unit correct");
|
||||
|
||||
|
||||
RELEASE(cal);
|
||||
|
||||
END_SET("NSCalendar date component differences")
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue