#include "LCDateTools.h" #include "GNUstep.h" /** * Provides support for converting dates to strings and vice-versa. * The strings are structured so that lexicographic sorting orders * them by date, which makes them suitable for use as field values * and search terms. * *
This class also helps you to limit the resolution of your dates. Do not * save dates with a finer resolution than you really need, as then * RangeQuery and PrefixQuery will require more memory and become slower. * *
Compared to {@link DateField} the strings generated by the methods
* in this class take slightly more space, unless your selected resolution
* is set to Resolution.DAY
or lower.
*/
@implementation NSString (LuceneKit_Document_Date)
/** convert a date to string in this format depending on resolution:
* "%Y%m%d%H%M%S%F" (yyyyMMddHHmmssSSS) in GMT.
*/
+ (id) stringWithCalendarDate: (NSCalendarDate *) date
resolution: (LCResolution) res;
{
return [NSString stringWithTimeIntervalSince1970: [date timeIntervalSince1970]
resolution: res];
}
/** convert a millisecond to string in this format depending on resolution:
* "%Y%m%d%H%M%S%F" (yyyyMMddHHmmssSSS) in GMT.
*/
+ (id) stringWithTimeIntervalSince1970: (NSTimeInterval) time
resolution: (LCResolution) resolution;
{
NSTimeInterval interval;
NSCalendarDate *date;
NSString *pattern;
date = [NSCalendarDate dateWithTimeIntervalSince1970: time];
interval = [date timeIntervalSince1970WithResolution: resolution];
date = [NSCalendarDate dateWithTimeIntervalSince1970: interval];
/* Make sure date is in GMT format */
[date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]];
if (resolution == LCResolution_YEAR) {
pattern = @"%Y";
} else if (resolution == LCResolution_MONTH) {
pattern = @"%Y%m";
} else if (resolution == LCResolution_DAY) {
pattern = @"%Y%m%d";
} else if (resolution == LCResolution_HOUR) {
pattern = @"%Y%m%d%H";
} else if (resolution == LCResolution_MINUTE) {
pattern = @"%Y%m%d%H%M";
} else if (resolution == LCResolution_SECOND) {
pattern = @"%Y%m%d%H%M%S";
} else if (resolution == LCResolution_MILLISECOND) {
pattern = @"%Y%m%d%H%M%S%F";
} else {
return nil; // Unknown Resolution
}
return [date descriptionWithCalendarFormat: pattern];
}
/**
* Converts a string produced by timeToString
or
* dateToString
back to a time, represented as the
* number of milliseconds since January 1, 1970, 00:00:00 GMT.
*
* @param dateString the date string to be converted
* @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
* @throws ParseException if dateString
is not in the
* expected format
*/
- (NSTimeInterval) timeIntervalSince1970
{
return [[self calendarDate] timeIntervalSince1970];
}
/* Convert a string in this format to date:
* "%Y%m%d%H%M%S%F" (yyyyMMddHHmmssSSS) in GMT.
*/
- (NSCalendarDate *) calendarDate;
{
NSString *pattern = nil;
int len = [self length];
switch(len)
{
case 4:
pattern = @"%Y%Z";
break;
case 6:
pattern = @"%Y%m%Z";
break;
case 8:
pattern = @"%Y%m%d%Z";
break;
case 10:
pattern = @"%Y%m%d%H%Z";
break;
case 12:
pattern = @"%Y%m%d%H%M%Z";
break;
case 14:
pattern = @"%Y%m%d%H%M%S%Z";
break;
case 17:
pattern = @"%Y%m%d%H%M%S%F%Z";
break;
default:
return nil; // Not Valid Date String
}
/* make sure the string is in GMT format */
return [NSCalendarDate dateWithString: [self stringByAppendingString:@"GMT"]
calendarFormat: pattern];
}
@end
@implementation NSCalendarDate (LuceneKit_Document_Date)
/**
* Limit a date's resolution. For example, the date 1095767411000
* (which represents 2004-09-21 13:50:11) will be changed to
* 1093989600000
(2004-09-01 00:00:00) when using
* Resolution.MONTH
.
*
* @param resolution The desired resolution of the date to be returned
* @return the date with all values more precise than resolution
* set to 0 or 1, expressed as milliseconds since January 1, 1970, 00:00:00 GMT
*/
- (NSTimeInterval) timeIntervalSince1970WithResolution: (LCResolution) res
{
return [[self dateWithResolution: res] timeIntervalSince1970];
}
/**
* Limit a date's resolution. For example, the date 2004-09-21 13:50:11
* will be changed to 2004-09-01 00:00:00
when using
* Resolution.MONTH
.
*
* @param resolution The desired resolution of the date to be returned
* @return the date with all values more precise than resolution
* set to 0 or 1
*/
- (NSCalendarDate *) dateWithResolution: (LCResolution) res
{
switch(res)
{
case LCResolution_YEAR:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: 1
day: 1
hour: 0
minute: 0
second: 0
timeZone: [self timeZone]];
case LCResolution_MONTH:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: [self monthOfYear]
day: 1
hour: 0
minute: 0
second: 0
timeZone: [self timeZone]];
case LCResolution_DAY:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: [self monthOfYear]
day: [self dayOfMonth]
hour: 0
minute: 0
second: 0
timeZone: [self timeZone]];
case LCResolution_HOUR:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: [self monthOfYear]
day: [self dayOfMonth]
hour: [self hourOfDay]
minute: 0
second: 0
timeZone: [self timeZone]];
case LCResolution_MINUTE:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: [self monthOfYear]
day: [self dayOfMonth]
hour: [self hourOfDay]
minute: [self minuteOfHour]
second: 0
timeZone: [self timeZone]];
case LCResolution_SECOND:
return [NSCalendarDate dateWithYear: [self yearOfCommonEra]
month: [self monthOfYear]
day: [self dayOfMonth]
hour: [self hourOfDay]
minute: [self minuteOfHour]
second: [self secondOfMinute]
timeZone: [self timeZone]];
case LCResolution_MILLISECOND:
return AUTORELEASE([self copy]);
// don't cut off anything
default:
return nil; // Error;
}
}
@end