Author: thebeing
Date: Mon Nov 30 11:06:04 2015
New Revision: 39202

URL: http://svn.gna.org/viewcvs/gnustep?rev=39202&view=rev
Log:
Implement -components:fromDate:toDate:options:

Added:
    libs/base/trunk/Tests/base/NSCalendar/component-diff.m
Modified:
    libs/base/trunk/ChangeLog
    libs/base/trunk/Headers/Foundation/NSCalendar.h
    libs/base/trunk/Source/NSCalendar.m

Modified: libs/base/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=39202&r1=39201&r2=39202&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog   (original)
+++ libs/base/trunk/ChangeLog   Mon Nov 30 11:06:04 2015
@@ -1,3 +1,12 @@
+2015-11-30: Niels Grewe <[email protected]>
+
+       * 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 <[email protected]>
 
        * Source/NSFileManager.m (createDirectoryAtPath)

Modified: libs/base/trunk/Headers/Foundation/NSCalendar.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Headers/Foundation/NSCalendar.h?rev=39202&r1=39201&r2=39202&view=diff
==============================================================================
--- libs/base/trunk/Headers/Foundation/NSCalendar.h     (original)
+++ libs/base/trunk/Headers/Foundation/NSCalendar.h     Mon Nov 30 11:06:04 2015
@@ -194,6 +194,17 @@
 
 - (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

Modified: libs/base/trunk/Source/NSCalendar.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSCalendar.m?rev=39202&r1=39201&r2=39202&view=diff
==============================================================================
--- libs/base/trunk/Source/NSCalendar.m (original)
+++ libs/base/trunk/Source/NSCalendar.m Mon Nov 30 11:06:04 2015
@@ -367,12 +367,81 @@
 #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

Added: libs/base/trunk/Tests/base/NSCalendar/component-diff.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Tests/base/NSCalendar/component-diff.m?rev=39202&view=auto
==============================================================================
--- libs/base/trunk/Tests/base/NSCalendar/component-diff.m      (added)
+++ libs/base/trunk/Tests/base/NSCalendar/component-diff.m      Mon Nov 30 
11:06:04 2015
@@ -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;
+}


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to