On 03/20/2013 08:18 AM, Richard Frith-Macdonald wrote:
Thanks ... I'll update the version macros in the header.
Please could you resubmit the patch for the new methods with
regression tests to demonstrate their function (and comments in the
header to document what they should do).
Here's an updated patch. I think the documentation is now even slightly
better than what Apple has :-)
I've also created a test file. It checks for a corner case (2012-12-31
is special when it comes to week and year numbers).
It also helped me find a pre-existing bug in NSCalendar in month number
handling.
--
Luboš Doležel
--- gnustep-base-1.24.3/Source/NSCalendar.m.orig 2013-01-24 10:15:53.000000000 +0100
+++ gnustep-base-1.24.3/Source/NSCalendar.m 2013-03-20 15:38:13.286123764 +0100
@@ -286,7 +286,7 @@
if (unitFlags & NSYearCalendarUnit)
[comps setYear: ucal_get (_cal, UCAL_YEAR, &err)];
if (unitFlags & NSMonthCalendarUnit)
- [comps setMonth: ucal_get (_cal, UCAL_MONTH, &err)];
+ [comps setMonth: ucal_get (_cal, UCAL_MONTH, &err)+1];
if (unitFlags & NSDayCalendarUnit)
[comps setDay: ucal_get (_cal, UCAL_DAY_OF_MONTH, &err)];
if (unitFlags & NSHourCalendarUnit)
@@ -295,12 +295,16 @@
[comps setMinute: ucal_get (_cal, UCAL_MINUTE, &err)];
if (unitFlags & NSSecondCalendarUnit)
[comps setSecond: ucal_get (_cal, UCAL_SECOND, &err)];
- if (unitFlags & NSWeekCalendarUnit)
+ if (unitFlags & (NSWeekCalendarUnit|NSWeekOfYearCalendarUnit))
[comps setWeek: ucal_get (_cal, UCAL_WEEK_OF_YEAR, &err)];
if (unitFlags & NSWeekdayCalendarUnit)
[comps setWeekday: ucal_get (_cal, UCAL_DAY_OF_WEEK, &err)];
if (unitFlags & NSWeekdayOrdinalCalendarUnit)
- [comps setWeekdayOrdinal: ucal_get (_cal, UCAL_WEEK_OF_MONTH, &err)];
+ [comps setWeekdayOrdinal: ucal_get (_cal, UCAL_DAY_OF_WEEK_IN_MONTH, &err)];
+ if (unitFlags & NSWeekOfMonthCalendarUnit)
+ [comps setWeekOfMonth: ucal_get (_cal, UCAL_WEEK_OF_MONTH, &err)];
+ if (unitFlags & NSYearForWeekOfYearCalendarUnit)
+ [comps setYearForWeekOfYear: ucal_get (_cal, UCAL_YEAR_WOY, &err)];
return AUTORELEASE(comps);
#else
@@ -370,6 +374,14 @@
{
_ADD_COMPONENT(UCAL_DAY_OF_WEEK, amount);
}
+ if ((amount = (int32_t)[comps weekOfMonth]) != NSUndefinedDateComponent)
+ {
+ _ADD_COMPONENT(UCAL_WEEK_OF_MONTH, amount);
+ }
+ if ((amount = (int32_t)[comps yearForWeekOfYear]) != NSUndefinedDateComponent)
+ {
+ _ADD_COMPONENT(UCAL_YEAR_WOY, amount);
+ }
#undef _ADD_COMPONENT
udate = ucal_getMillis (_cal, &err);
@@ -402,7 +414,7 @@
}
if ((amount = (int32_t)[comps month]) != NSUndefinedDateComponent)
{
- ucal_set (_cal, UCAL_MONTH, amount);
+ ucal_set (_cal, UCAL_MONTH, amount-1);
}
if ((amount = (int32_t)[comps day]) != NSUndefinedDateComponent)
{
@@ -428,6 +440,14 @@
{
ucal_set (_cal, UCAL_DAY_OF_WEEK, amount);
}
+ if ((amount = (int32_t)[comps weekOfMonth]) != NSUndefinedDateComponent)
+ {
+ ucal_set (_cal, UCAL_WEEK_OF_MONTH, amount);
+ }
+ if ((amount = (int32_t)[comps yearForWeekOfYear]) != NSUndefinedDateComponent)
+ {
+ ucal_set (_cal, UCAL_YEAR_WOY, amount);
+ }
udate = ucal_getMillis (_cal, &err);
if (U_FAILURE(err))
@@ -672,6 +692,10 @@
_weekday = NSUndefinedDateComponent;
_weekdayOrdinal = NSUndefinedDateComponent;
_quarter = NSUndefinedDateComponent;
+ _weekOfMonth = NSUndefinedDateComponent;
+ _yearForWeekOfYear = NSUndefinedDateComponent;
+ _cal = NULL;
+ _tz = NULL;
return self;
}
@@ -731,6 +755,21 @@
return _year;
}
+- (NSInteger) weekOfMonth
+{
+ return _weekOfMonth;
+}
+
+- (NSInteger) weekOfYear
+{
+ return _week;
+}
+
+- (NSInteger) yearForWeekOfYear
+{
+ return _yearForWeekOfYear;
+}
+
- (NSCalendar *) calendar
{
return _cal;
@@ -741,6 +780,16 @@
return _tz;
}
+- (NSDate *) date
+{
+ NSCalendar* cal = [self calendar];
+ NSTimeZone* zone = [self timeZone];
+
+ if (zone != NULL)
+ [cal setTimeZone: zone];
+
+ return [cal dateFromComponents: self];
+}
- (void) setDay: (NSInteger) v
@@ -798,6 +847,21 @@
_year = v;
}
+- (void) setWeekOfYear: (NSInteger) v
+{
+ _week = v;
+}
+
+- (void) setWeekOfMonth: (NSInteger) v
+{
+ _weekOfMonth = v;
+}
+
+- (void) setYearForWeekOfYear: (NSInteger) v
+{
+ _yearForWeekOfYear = v;
+}
+
- (void) setCalendar: (NSCalendar *) cal
{
if (_cal)
--- gnustep-base-1.24.3/Headers/Foundation/NSCalendar.h.orig 2013-03-19 13:58:09.155292011 +0100
+++ gnustep-base-1.24.3/Headers/Foundation/NSCalendar.h 2013-03-20 15:55:58.750426053 +0100
@@ -56,7 +56,12 @@
NSWeekdayCalendarUnit = (1UL << 9),
NSWeekdayOrdinalCalendarUnit = (1UL << 10),
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
- NSQuarterCalendarUnit = (1UL << 11)
+ NSQuarterCalendarUnit = (1UL << 11),
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
+ NSWeekOfMonthCalendarUnit = (1UL << 12),
+ NSWeekOfYearCalendarUnit = (1UL << 13),
+ NSYearForWeekOfYearCalendarUnit = (1UL << 14),
#endif
};
@@ -85,11 +90,11 @@
NSInteger _weekday;
NSInteger _weekdayOrdinal;
NSInteger _quarter;
-// FIXME: In reality these are only available on iOS > 4. Will probably show
-// up in OS X 10.7.
-#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
NSCalendar *_cal;
NSTimeZone *_tz;
+ NSInteger _weekOfMonth;
+ NSInteger _yearForWeekOfYear;
#endif
}
@@ -120,13 +125,54 @@
- (void) setQuarter: (NSInteger) v;
#endif
-// FIXME: In reality these are only available on iOS > 4.
-#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
- (NSCalendar *) calendar;
- (NSTimeZone *) timeZone;
- (void) setCalendar: (NSCalendar *) cal;
- (void) setTimeZone: (NSTimeZone *) tz;
+
+/**
+ * <p>
+ * Computes a date by using the components set in this NSDateComponents
+ * instance.
+ * </p>
+ * <p>
+ * A calendar (and optionally a time zone) must be set prior to
+ * calling this method.
+ * </p>
+ */
+- (NSDate *) date;
+
+/** Returns the number of the week in this month. */
+- (NSInteger) weekOfMonth;
+/**
+ * Returns the number of the week in this year.
+ * Identical to calling <code>week</code>. */
+- (NSInteger) weekOfYear;
+/**
+ * The year corresponding to the current week.
+ * This value may differ from year around the end of the year.
+ *
+ * For example, for 2012-12-31, the year number is 2012, but
+ * yearForWeekOfYear is 2013, since it's already week 1 in 2013.
+ */
+- (NSInteger) yearForWeekOfYear;
+
+/** Sets the number of the week in this month. */
+- (void) setWeekOfMonth: (NSInteger) v;
+
+/**
+ * Sets the number of the week in this year.
+ * Identical to calling <code>-setWeek</code>. */
+- (void) setWeekOfYear: (NSInteger) v;
+
+/**
+ * Sets the year number for the current week.
+ * See the explanation at <code>-yearForWeekOfYear</code>.
+ */
+- (void) setYearForWeekOfYear: (NSInteger) v;
#endif
+
@end
#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 10.7 features")
if (!NSCALENDAR_SUPPORTED)
SKIP("NSCalendar not supported\nThe ICU library was not available when
GNUstep-base was built")
cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
date = [NSDate dateWithString: @"2012-12-31 13:57:00 +0100"];
comps = [cal components: NSYearForWeekOfYearCalendarUnit
| NSWeekOfYearCalendarUnit | NSWeekOfMonthCalendarUnit
fromDate: date];
PASS([comps weekOfMonth] == 6, "-weekOfMonth returns the correct week");
PASS([comps weekOfYear] == 1, "-weekOfYear returns the correct week");
PASS([comps yearForWeekOfYear] == 2013, "-yearForWeekOfYear returns the
correct year");
comps = [[NSDateComponents alloc] init];
[comps setCalendar: cal];
[comps setTimeZone: [NSTimeZone defaultTimeZone]];
[comps setHour: 13];
[comps setMinute: 57];
[comps setDay: 31];
[comps setMonth: 12];
[comps setYear: 2012];
date2 = [comps date];
PASS([date isEqual: date2], "-[NSDateComponents date] returns the correct
date");
RELEASE(comps);
RELEASE(cal);
END_SET("NSCalendar 10.7 features")
return 0;
}
_______________________________________________
Gnustep-dev mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/gnustep-dev