Code Monkey home page Code Monkey logo

iso-8601-date-formatter's Introduction

ISO 8601: The only date format worth using

Image: Status of most recent build and test attempt. Image: Test code coverage percentage.

Obligatory relevant xkcd:

Seriously now. “ISO 8601 was published on 06/05/88 and most recently amended on 12/01/04.”

How to use this code in your program

Add the source files to your project.

Parsing

Create an ISO 8601 date formatter, then call [formatter dateFromString:myString]. The method will return either an NSDate or nil.

There are a total of six parser methods. The one that contains the actual parser is -[ISO8601DateFormatter dateComponentsFromString:timeZone:range:]. The other five are based on this one.

The “outTimeZone” parameter, when not set to NULL, is a pointer to an NSTimeZone *variable. If the string specified a time zone, you'll receive the time zone object in that variable. If the string didn't specify a time zone, you'll receive nil.

The “outRange” parameter, when not set to NULL, is a pointer to NSRange storage. You will receive the range of the parsed substring in that storage.

Unparsing

Create an ISO 8601 date formatter, then call [formatter stringFromDate:myDate]. The method will return a string.

The formatter has several properties that control its behavior:

  • You can set the format of the resulting strings. By default, the formatter will generate calendar-date strings; your other options are week dates and ordinal dates.
  • You can set a default time zone; by default, it will use [NSTimeZone defaultTimeZone].
  • You can enable a strict mode, wherein the formatter enforces sanity checks on the string. By default, the parser will afford you quite a bit of leeway.
  • You can set whether to include the time in the string, and if so, what hour-minute separator to use (default ':').

How to test that this code works

UPDATE from the year 2013: Conversion from the old make-based test monsters to modern OCUnit-based tests is underway. Contributions of new and old test cases will be greatly appreciated.

'make test' will perform all tests. If you want to perform only some tests:

Parsing

Type 'make parser-test'. make will build the test program (testparser), then invoke testparser.sh.py to generate testparser.sh. Then make will invoke testparser.sh, which will invoke the test program with various dates.

If you don't want to use my tests, 'make testparser' will create the test program without running it. You can then invoke testparser yourself with any date you want to. If it doesn't give you the result you expected, contact me, making sure to provide me with both the input and the output.

Unparsing

Type 'make unparser-test'. make will build the test programs, then invoke testunparser.sh. This shell script invokes each test program for -01-01 of every year from 1991 to 2010, writing the output to a file, and then runs diff -qs between that file (testunparser.out) and a file (testunparser-expected.out) containing known correct output. diff should report that the files are identical.

Three test programs are included: unparse-date, unparse-weekdate, and unparse-ordinal date. If you don't want to use my tests, you can make these test programs separately. Each takes a date specified by ISO 8601 (parsed with my own ISO 8601 parser), and outputs a string that should represent the same date.

Notes

Version history

This version is 0.8. Changes from 0.7:

  • watchOS is now officially supported. ba5cbc3 de905a1 45ab5eb (Thanks, Neil Daniels!)
  • tvOS is now officially supported. b56be72 (Thanks, Boris Bügling!)
  • Carthage is now officially supported. da460bf (Thanks, Agnes Vasarhelyi!)
  • Added support for millisecond precision. 065612a (Thanks, Rob Keniger!)
  • Fixed bug that could insert the sign character into the middle of time zone specifications. 7b189ae 5ceb8d6 (Thanks, Hector Zarate!)
  • Improved thread safety of time zone cache. 98bf9cb (Thanks, Peter Steinberger!)
  • Tests now use XCTest. 3cb3921 591ca75
  • API now declares nullability. 40ba01d
  • Header documentation should now be parseable by Xcode. a76f42c 54136ac
  • Updated link to Rick McCarty's week dates algorithm. 58f3d26 (Thanks, Christopher Bowns!)
  • Begun the move to newer API names. 446b9f3 (Thanks, William Kent!)
  • Maintained support for legacy runtime (i386 Mac) targets. c02cffe 01ea541 (Thanks, Mike Abdullah!)
  • Fixed a build error that was introduced by SDK changes. 6d01598 (Thanks, Kyle Fuller!)
  • Fixed an uninitialized variable. 1b09a6a (Thanks, Marcel Jackwerth!)

This version is 0.7. Changes from 0.6:

  • Cocoa Touch is now officially supported. 4bc0a08 5d95233
  • Added an Xcode project with static library targets. c847ddb 4bc0a08
  • stringFromObjectValue: now logs to the Console when you hand it a value that isn't an NSDate. Check your Console output after upgrading—you might have had a bug all this time without knowing! 4e05978
  • Added proper documentation in the header, compatible with appledoc. f17713f
  • Fixed nonsense date components/dates being returned when the input is not a valid date string. 288f757 93bb9df 0cb6442
  • Fixed a bug in unparsing where the time zone was wrong (#3). 0e355ee 8f8a2c3 (Thanks, Carl Lindberg)
  • Fixed a DST bug in unparsing where the time zone offset was computed in general rather than for the date being unparsed (#6). 5665132 (Thanks, Zachary West) 9e835c8 0d36057
  • Fixed AM/PM (or local equivalent) appearing in some locales on iOS devices (#15). 4bc0a08 3f697b5 249b3df (Thanks, Matthias Bauch)
  • Fixed another NSDateFormatter-rewriting-formats-to-12-hour-in-some-locales bug. 7c9907f (Thanks, Carl Lindberg)
  • (iOS) The class now purges its time zone cache automatically in response to a memory warning. You don't need to do that yourself, anymore, so the method to purge the caches is no longer public. 138e186 3224b32 a9b6973 3f3c3b8
  • Added support for strings that specify a fraction of a second. 1d3194b 0b0b1ea (Thanks, Luke Redpath)
  • Added support for non-ASCII time separator characters. 47d5035
  • Added support for a time zone separator. 8198f1b 3bd0c07 17c15ed (Thanks to Daniel Tull for the suggestion.)
  • Fixed the parser's response to being passed nil. 3c12abc 4980ee6
  • Fixed (I think) #5: dates being formatted with DST applied when they shouldn't. 7368fe8
  • Fixed stringFromObjectValue: to behave as NSFormatter's documentation says it should. 3846f80 9754438
  • Added real unit tests based on OCUnit. c847ddb aa1c2cb daf3cc9 9029991 d92aeb6 b412326 (Thanks, Luke Redpath) 45af6bd cfedd75 af0b93c 6a7fd88 9e835c8 9e835c8 0d36057 7368fe8 4bc0a08 3f697b5 8f8a2c3 51c1130 e888681 13a872d f49193c 10ed166 d5fdf51 4980ee6 3846f80 288f757 93bb9df daa45fb 2d61bd0 9f35c4a 8f95099 d62777a 138e186 2a63718
  • Fixed range computation for strings where the date portion ends with a 'Z'. 8f95099 efa095e 808e8c4
  • Fixed some formats with missing hyphens being wrongly accepted when strict mode is on. 9f35c4a c4e0f15
  • Fixed week date strings not having a 'T' between date and time. 7b6fd9f 6a1b66b
  • Fixed week date strings having wrong time zones. 9f6af7c
  • Strings that specify intervals (as specified by ISO 8601) are now explicitly rejected, at least for now (#20). 6d539db 51c1130 bf6a2db 6aef760 (Thanks, Blake Watters)
  • ISO8601DefaultTimeSeparatorCharacter is now declared as const. I hope none of you were relying on changing that. db9877c
  • Upgraded this README to Markdown. 103f666 fbd34b2 ebbf65a c0b9609
  • Added the above xkcd comic. fbd34b2 63ba50a da3ed65
  • Some light modernization (#25, #28). cdec3e9 8df32fd bb7c5c9

Changes in 0.6 from 0.5:

  • When not set to strict parsing, allow a space before the time-zone specification, for greater compatibility with NSDate output (description) and input (dateWithString:). 27603efc8a77
  • Bug fix: We no longer try to format the formatter. 83415de9f527
  • Bug fix: Hours are now zero-padded correctly (#4). a5608e189ebe af0c6b397428
  • Fixed many various compiler warnings. Some fixes contributed by Sparks. 8be3d6f7c6f2 78ae31de2170 68dc351e9fdb e7ea87db8621 873f499ae6db
  • Now 75 times faster. 6a023812bd2b 05dc35d6b505 3b2225e0ce8c d59720ad015a 10f526956963 297b8dae4095 796be11aa596 cadf0f0c8199 61d2959c6921
  • iOS users can now tell the ISO 8601 date formatter class to drop its caches (which you should do when you receive a memory warning). 2bb1725914b1
  • Added a couple of command-line options to the calendar-format-unparser test tool. c644aadb2b14
  • The parser test tool now displays parsed dates in GMT rather than the local time zone. 788c1455ecb1
  • Added a test tool to test unparsing with the time included. a89a9a8b3d61
  • You can now “make analysis” to run the Clang Static Analyzer on the date formatter. b3dd33841f42
  • The test tools are now built using Clang. 0723d3aa6596

Changes in 0.5 from 0.4:

  • Rewrote as an NSFormatter subclass using NSCalendar.
    • Making it a formatter makes it much easier to use with Bindings.
    • Using NSCalendar means we're no longer using NSCalendarDate, which Apple has said they will deprecate at some point.
  • Fixed a bug in week date generation: One subtraction could give a negative result, which was a problem because my implementation of the algorithm used unsigned integers. I've changed it to use signed integers, so the result truly is negative now. I also added a test case for this.

Changes in 0.4 from 0.3:

  • Added the ability to use a time separator other than ':'.

Changes in 0.3 from 0.2:

  • Colin Barrett noticed that I used %m instead of %M when creating the time strings. Oops.
  • Colin also noticed that I had the ?: in ISO8601DateStringWithTime: the wrong way around. Oops again.

Changes in 0.2 from 0.1:

  • The unparser is new. The has been munged to allow both components together,
  • The parser has not changed.

Implementation details

Parsing

Whitespace before a date, and anything after a date, is ignored. Thus, " T23 and all's well" is a valid date for the purpose of this method. (Yes, T23 is a valid ISO 8601 date. It means 23:00:00, or 11 PM.)

All of the frills of ISO 8601 are supported, except for extended dates (years longer than 4 digits). Specifically, you can use week-based dates (2006-W2 for the second week of 2006), ordinal dates (2006-365 for December 31), decimal minutes (11:30.5 == 11:30:30), and decimal seconds (11:30:10.5). All methods of specifying a time zone are supported.

ISO 8601 leaves quite a bit up to the parties exchanging dates. I hope I've chosen reasonable defaults. For example (note that I'm writing this on 2006-02-24):

  • If the month or month and date are missing, 1 is assumed. "2006" == "2006-01-01".
  • If the year or year and month are missing, the current ones are assumed. "--02-01" == "2006-02-01". "---28" == "2006-02-28".
  • In the case of week-based dates, with the day missing, this implementation returns the first day of that week: 2006-W1 is 2006-01-01, 2006-W2 is 2006-01-08, etc.
  • For any date without a time, midnight on that date is used.
  • ISO 8601 permits the choice of either T0 or T24 for midnight. This implementation uses T0. T24 will get you T0 on the following day.
  • If no time-zone is specified, local time (as returned by [NSTimeZone localTimeZone]) is used.

None of the above defaults apply if you're using the NSDateComponents-based API.

When a date is parsed that has a year but no century, this implementation adds the current century.

The implementation is tolerant of out-of-range numbers. For example, "2005-13-40T24:62:89" == 1:02 AM on 2006-02-10. Notice that the month (13 > 12), date (40 > 31), hour (24 > 23), minute (62 > 59), and second (89 > 59) are all out-of-range.

As mentioned above, there is a "strict" mode that enforces sanity checks. In particular, the date must be the entire contents of the string, and numbers are range-checked. If you have any suggestions on how to make this mode more strict, please file an enhancement request in the Issues section.

Unparsing

I use Rick McCarty's algorithm for converting calendar dates to week dates, slightly tweaked.

Bugs

Parsing

  • This method won't extract a date from just anywhere in a string, only immediately after the start of the string (or any leading whitespace). There are two solutions: either require you to invoke the parser on a string that is only an ISO 8601 date, with nothing before or after (bad for parsing purposes), or make the parser able to find an ISO 8601 date as a substring. I won't do the first one, and barring a patch, I probably won't do the second one either.

  • Date ranges (also specified by ISO 8601) are not supported; this method will only return one date. To handle ranges would require at least one more method.

  • There is no method to analyze a date string and tell you what was found in it (year, month, week, day, ordinal day, etc.). Feel free to submit a patch.

Contributing

This project adheres to [the Contributor Covenant, version 1.4](CODE OF CONDUCT.md). Please read that before deciding whether you are willing to contribute.

You're welcome to work on any open bug in the issue tracker, but we do have some that are up-for-grabs that are particularly easy or potentially interesting.

Please don't break compatibility with old OS versions (OS X 10.7/iOS 4) until work begins on the 1.0 release. That won't happen until 0.9 is done, and starting 1.0-only work (e.g., ARCification) early will lead to conflicts.

The tests use ARC, but the formatter itself does not (yet). Please be sure to add the needed release or autorelease messages when adding code that creates objects.

Adding test cases is highly encouraged, especially if adding new functionality. Ideally, please test a comprehensive set of:

  • success cases
  • failure cases
  • exception (programmer error) cases: even if something isn't supported, the behavior should still be reliable and preferably diagnostically helpful

Travis CI will run the tests automatically when you submit a pull request, and a PR with failing tests will not be accepted.

Contributions consisting of nothing but test cases are welcome. If one/some of those cases fail, please include fixes, or at least, submit an issue report for the failure(s) and surround the failing tests with:

#if FIXED_(issue number)
- (void) test_thingThatDoesntWorkButShould {
    ⋮
}
#endif FIXED_(issue number)

As far as code style, mostly, please try to remain consistent with the existing code. Please do add nullability annotations (ISO8601_NULLABLE/ISO8601_NONNULL) and const to new code whenever applicable.

Copyright

This code is copyright 2006–2016 Peter Hosey. It is under the BSD license; see LICENSE.txt for the full text of the license.

iso-8601-date-formatter's People

Contributors

amarcadet avatar boredzo avatar carllindberg avatar cbowns avatar chocochipset avatar danielctull avatar kylef avatar lukeredpath avatar mastohhh avatar mattbauch avatar mikeabdullah avatar monerobby avatar mrcljx avatar neildaniels avatar neonichu avatar steipete avatar vasarhelyia avatar wjk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iso-8601-date-formatter's Issues

iOS8/10.10 vs Apple's NSCalendar/NSDate refactoring... time for fork?

So, under iOS8 (and, I presume, Yosemite, since this is about a foundation class) presents a number of deprecation warnings -- mostly things like constants who names have changed, when trying to compile the date formatter, e.g.:

ISO8601DateFormatter.m:216:86: warning: 'NSMonthCalendarUnit' is deprecated: first deprecated in iOS 8.0 - Use NSCalendarUnitMonth instead

These could be fixed by conditionalizing the code, but that will get very ugly instantaneously - is there a plan to address this in another way? Would it make sense to make a "modern" fork for people using iOS8/Yosemite and above?

Cocoa Touch tests should simulate a memory warning

A test case in the Cocoa Touch test bundle target could and should post the notification that ordinarily the system posts in the event of a memory warning, in order to test that the ISO 8601 Date Formatter responds appropriately.

+dateString:isEqualToDateString:

This class method would parse two ISO 8601 date strings and return whether they are equal.

Matters for debate:

  • Should the parsing be strict?
  • How exact should the comparison be? (Ideal, I suppose, would be detect how much information is in each string—e.g., whether one omits seconds—and accept equality within that level of granularity.)
  • What options, if any, should be provided for customization of the comparison? (E.g., whether parsing is strict or not.)

firstWeekday set to 2

Just curious why firstWeekday is set to 2 instead of depending on NSLocale or [NSCalendar currentCalendar].

Nullability

The API should declare the nullability of method arguments, return types, and property values, and this should be enforced (where appropriate) in the tests.

- (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone App got crashed.

Here is crash log:

0 libdispatch.dylib 0x1d3191be _dispatch_semaphore_dispose + 80 (semaphore.c:69)
1 Foundation 0x1e510b20 -[NSDateFormatter dealloc] + 74 (NSDateFormatter.m:291)
2 libobjc.A.dylib 0x1cee9258 objc_object::sidetable_release(bool) + 238 (NSObject.mm:1591)
3 ISO8601DateFormatter 0x0117e522 -[ISO8601DateFormatter stringFromDate:formatString:timeZone:] + 228 (ISO8601DateFormatter.m:716)
4 ISO8601DateFormatter 0x0117e3e6 -[ISO8601DateFormatter stringFromDate:timeZone:] + 132 (ISO8601DateFormatter.m:697)

When see code we are deallocating formatter but due to crash it's not going further steps where it's getting allocated.

if ([dateFormat isEqualToString:lastUsedFormatString] == NO) {
[unparsingFormatter release];
unparsingFormatter = nil;

	[lastUsedFormatString release];
	lastUsedFormatString = [dateFormat retain];
}

if (!unparsingFormatter) {
	unparsingFormatter = [[NSDateFormatter alloc] init];
	unparsingFormatter.formatterBehavior = NSDateFormatterBehavior10_4;
	unparsingFormatter.dateFormat = dateFormat;
	unparsingFormatter.calendar = unparsingCalendar;
	unparsingFormatter.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
}

Any inputs to fix this are welcome.

'ISO8601DateFormatter' is ambiguous for type lookup in this context

I'm updating my project to use Swift 3.0 and on 3.0 , NSISO8601DateFormatter becomes just ISO8601DateFormatter, which conflicts with this library.

Unfortunately, using ISO8601DateFormatter.ISO8601DateFormatter doesn't help either (seems to be a compiler bug: https://bugs.swift.org/browse/SR-1386).

An easy way to fix this would be using module_name in the Podspec (https://guides.cocoapods.org/syntax/podspec.html#module_name) to change the module to something else, allowing SomeModule.ISO8601DateFormatter.

Installation section

Hey, your library is really interesting.

The only problem I found was the README.md, which lacks an Installation Section
I created this iOS Open source Readme Template so you can take a look on how to easily create an Installation Section
If you want, I can help you to organize the Readme.

What are your thoughts? 😄

Update Podspec to support watchOS 2

When using ISO8601DateFormatter with watchOS 2, then I get this error message when running pod install

[!] The platform of the target `XXXX` (watchOS 2.0) is not compatible with `ISO8601DateFormatter (0.7)`, which does not support `watchos`.

Please update the podspec for ISO8601DateFormatter to support watchOS 2.

Here's the Cocoapods blog entry: http://blog.cocoapods.org/CocoaPods-0.38/

dateComponentsFromString: methods make stuff up

The dateComponentsFromString: methods fill in anything not specified by the string with the corresponding components from the current local date/time.

This is an artifact of the old, pre-NSDateComponents design. In the current design, it is broken behavior.

The components should not contain any information not directly sourced from the input string. Interpolation of missing components should happen in dateFromString:, if at all.

How do I create a date string from a date without including any daylight saving?

NSString* dateString = @"2012-04-01T15:37:53Z";

ISO8601DateFormatter *dateFormat = [[ISO8601DateFormatter alloc] init];
[dateFormat setIncludeTime:YES];
NSTimeZone *utcTimeZone = [NSTimeZone timeZoneWithName:@"UTC"];

NSDate* date = [dateFormat dateFromString:dateString timeZone:&utcTimeZone];

STAssertEqualObjects([dateFormat stringFromDate:date timeZone:utcTimeZone], dateString, nil, nil);

The above test fails with

'2012-04-01T16:37:53Z' should be equal to '2012-04-01T15:37:53Z'

Not sure why the NSString returned by the stringFromDate:date is 1 hour later since both dates are using UTC.

Odd output from date formatter (including AM/PM markers?)

I'm still investigating the whys and wherefores (as I only saw this in a production app calling the API) but we've seen output like this occasionally:

2013-08-02T01:35:00 PMZ

It looks like its formatting the time as 01:30:00 PM then adding the 'Z' zone?

I'll update this ticket as we find out more information the code that produces the string is this:

    ISO8601DateFormatter *fmt = [[ISO8601DateFormatter alloc] init];
    NSTimeZone * tz = [NSTimeZone localTimeZone];
    fmt.includeTime = YES;

    if(self.timezone)
    {
        tz = [NSTimeZone timeZoneWithName:self.timezone];
    }


    return [fmt stringFromDate:self.created
                      timeZone:tz];

In the error seen above self.timezone was @"GMT" (which is what cocoa calls UTC) I don't know anything about the locale of the specific device but I believe that could have affected this.

Tag Releases

Long ago, I created the @ISO8601DateFormatter organization to host a mirror of this library in order to be used with CocoaPods. One of the constraints is that official pods need to point to tags, so I added that to the fork. It was only recently that I found this repo on GitHub.

I'd love to shut down my org and point the old specs to this. All it would take is for you to tag your commits thusly:

Carthage build fails under 10.11

I received this issue the other day on my project and it seems this problem occurs under OS X 10.11 & Xcode 7.1 with the framework.

Building the project with Carthage gives an error like it's unable to find destination and the destination was a Core Simulator iPhone 4S, iOS 9.1. I've checked the build settings of the ISO8601 framework target and the only thing unfamiliar to me is that the architectures were not set to Standard (armv7, arm64). I gave it a try setting it standard and it solved this issue.

I've created an issue, not a PR because I'm not aware of why do you have different settings for architecture, I would appreciate your help clarifying it. Honestly, I have no idea why does setting it to standard solve this problem if it worked perfectly under 10.10 and Xcode 7.0, couldn't find any useful information about it. It might even be a Carthage issue, I will ask them for help as well.

Slay the test monsters

Currently, make test builds and runs a mess of shell, Python, and Objective-C code, which I've started referring to as the “test monsters”.

There are two test monsters. One of them does not even really test anything; it simply spews a bunch of output and leaves it to the person driving the machine to read it and scan for errors. (You tell me when the last time that actually happened was.) The other does test the output—using diff.

Now that we have (relatively) modern OCUnit-based tests, the test monsters should be slain.

This is blocked until all of the test cases worth caring about from the test monsters are ported over to OCUnit.

Once that's done, the test monsters should be killed off (and good riddance to them), and make test changed to run the Xcode tests.

New release?

I've noticed that the latest cocoapods spec for this library points to version 0.6 which is 2 years old now... Lots of things has been changed since that release :)

Usually a developer, who wants to add this library to his project via cocoapods will just add to Podfile:

pod 'ISO8601DateFormatter'

which will install 2 years old release...

Could you please mark some of the most recent stable commit with new tag? So we can add a new spec for this library to cocoapods.

Thanks in advance!

Use of undeclared identifier 'DBL_EPSILON'

Hi,

Trying to compile this into a static library and run in both the simulator and Instruments (Xcode 5.0.2, iOS SDK 7) I get an undefined error. At the top of the .m file you conditionally include the UIKit.h (which, if included removes this problem) if TARGET_OS_IPHONE is defined.

To get this to compile for the simulator, I had to add "|| TARGET_IPHONE_SIMULATOR" to the condition.

Any idea how to get it to compile for instruments?

Getting a false NSDate from string

Hi,

I'm using this components to get a NSDate from a string obtained from Facebook API, but I found the NSDate is not right.

I tried the code bellow:

ISO8601DateFormatter* formatter = [[ISO8601DateFormatter alloc] init];
NSDate* date = [formatter dateFromString:@"2014-12-01"];
And I get the date as 2014-11-30 16:00:00 +0000, it's one day before 2014-12-01.

Yes, I'm in China, it looks right if we count the timezone element in.

But, I have tried other components on ISO8601, for example https://github.com/soffes/ISO8601
I tried the code the same as above, and I get the date as 1999-05-01 00:00:00 +0000

I have read the doc, didn't find any clue to get the same result as ISO8601 from this components.

Could you please teach me how to get a date as 2014-11-30 16:00:00 +0000 using this components?

Thanks in advance.

BR,
roby

Cocoapods support

When I searched the CocoaPods site for this library, one result shows up.

Then I went and added it to my Podfile, ran pod install but I got the following error.
Unable to find a specification for iso-8601-date-formatter

Can you please implement CocoaPods support for your library? I'd really appreciate it.

Thanks.

Install via Carthage 0.9.1 fails

Dependency "iso-8601-date-formatter" has no shared framework schemes

I know the project has merged Carthage support recently, maybe it's a regression?

crash on method "dateComponentsFromString:timeZone:range:fractionOfSecond"

I am getting crash report from the wild that has the following stacktrace.

0 ...    libsystem_kernel.dylib  __pthread_kill + 8
1    libsystem_c.dylib   pthread_kill + 58
2    libsystem_c.dylib   abort + 94
3    libc++abi.dylib     abort_message + 74
4    libc++abi.dylib     __cxa_pure_virtual + 18
5    libicucore.A.dylib  icu::TimeZone::getOffset(double, signed char, int&, int&, UErrorCode&) const + 54
6    libicucore.A.dylib  icu::Calendar::computeFields(UErrorCode&) + 76
7    libicucore.A.dylib  icu::Calendar::complete(UErrorCode&) + 42
8    libicucore.A.dylib  icu::Calendar::get(UCalendarDateFields, UErrorCode&) const + 28
9    CoreFoundation  _CFCalendarDecomposeAbsoluteTimeV + 240
10   CoreFoundation  -[__NSCFCalendar components:fromDate:] + 580
11   TestApp    ISO8601DateFormatter.m line 216
-[ISO8601DateFormatter dateComponentsFromString:timeZone:range:fractionOfSecond:]

This is a result of calling "dateFromString" with a string "2013-10-09T13:00:00Z". This does not crash all the time since I can see that it works for other dates in my logs.

I do however create an instance of ISO8601DateFormatter in my AppDelegate like the following.

(ISO8601DateFormatter*) iso8601DateFormatter {
  if (!_iso8601DateFormatter) {
    _iso8601DateFormatter = [[ISO8601DateFormatter alloc] init];
  }
  return _iso8601DateFormatter;
}

Can not use ISO8601DateFormatter

This works:
self.time = unboxer.unbox(key: "time", formatter: DateFormatter())

But this does not:
self.time = unboxer.unbox(key: "time", formatter: ISO8601DateFormatter())

timeZonesByOffset is thread-unsafe

timeZonesByOffset is a global mutable dictionary accessed from multiple threads without synchronization, making independent date formatters unsafe to use from separate threads simultaneously.

Formatting does not fully respect time zone

Unless I'm missing something, it appears that while the time zone is being set in the associated NSCalendar instance, it is the timeZone set in the NSDateFormatter instance which is actually being used to format the time. Since the passed-in time zone is used to append the "Z" or the numeric time zone offset, the actual time seen can be a mismatch with the time zone. It appears as though the systemTimeZone or localTimeZone is being used by default.

The following program will print out different time values, even though they both appear to be using a UTC time zone, and both end up with a "Z" time zone in the string. The NSDateFormatter result is correct; ISO8601DateFormatter prints out an incorrect time (unless actually being run in a zero-offset time zone).

#import <Foundation/Foundation.h>
#import "ISO8601DateFormatter.h"

int main()
{
    id pool = [[NSAutoreleasePool alloc] init];

    ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init];
    [formatter setIncludeTime:YES];
    [formatter setDefaultTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; // UTC

    NSDateFormatter *nsformatter = [[NSDateFormatter alloc] init];
    [nsformatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
    [nsformatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; // UTC

    NSDate *date = [NSDate date];
    NSString *isoFormatted = [formatter stringFromDate:date];
    NSString *nsFormatted = [nsformatter stringFromDate:date];

    NSLog(@"\nISO:    %@\nNSDate: %@", isoFormatted, nsFormatted);

    [pool release];
    exit(0);
    return 0;
}

The problem is fixed if you set unparsingFormatter.timeZone to the same value as unparsingCalendar.timeZone in the code.

This is running on MacOS 10.7; problem also observed using iOS 5.x.

Don't import UIKit.h

The top of ISO8601DateFormatter.m imports UIKit.h, but nothing from this framework ever seems to be used.

It appears to have been added in a9b6973, and all usages removed in 98bf9cb.

Use NSISO8601DateFormatter when available

On macOS 10.12 and iOS 10, Foundation has an NSISO8601DateFormatter class built in. It'd be cool if ISO8601DateFormatter wrapped that implementation when it's available, as an aid to clients who'd like to move toward that implementation.

Ingredients:

  • Don't delete the existing implementation—clients supporting older OS versions will still need it.
  • Ensure calls to ISO8601DateFormatter methods reach NSISO8601DateFormatter implementations when available. There are many ways you could achieve this: Return an NSISO8601DateFormatter from alloc; have a class cluster; return the result of the NSISO8601DateFormatter implementation at the start of each ISO8601DateFormatter implementation—up to you.
  • NSISO8601DateFormatter property and method names may differ from those in ISO8601DateFormatter. Add methods with NSISO8601DateFormatter's names to ISO8601DateFormatter that call either the method of the same name on an actual NSISO8601DateFormatter (if possible) or the equivalent method in the ISO8601DateFormatter.

Refactor and Modernize ISO8601DateFormatter

Hi Peter -

Thanks so much for your most excellent contribution of ISO8601DateFormatter to the Cocoa Open Source community. It definitely has to be one of the most widely used libraries floating around.

Several years ago I integrated the library into RestKit/RestKit and have been maintaining a forked version of the library ever since. We have made a number of incremental improvements to the package. We are currently in the process of atomizing some parts of RestKit into smaller more modular libraries and one of the sticking points at the moment is the dependence on the forked copy of the date formatter.

This has put me in the position of either a) shipping a standalone competing implementation of the date formatter or b) trying to integrate our changes back into the mainline so that there is one authoritative code base out there. I'd prefer to go the latter route and wanted to reach out and gauge your enthusiasm for larger changes to the library.

I'd like to do the following:

  • Put an Xcode project on tree and integrate unit tests that aren't dependent on python / shell scripting.
  • Put the project under Travis CI for continuous integration of the tests.
  • Modernize the date formatter by updating it for ARC.
  • Integrate whatever fixes I have in my codebase that have not appeared in your main line and add appropriate test coverage.
  • Clean up the formatting and styling in use within the library to be more in line with modern idiomatic Cocoa.
  • Improve the thread-safety of the library by factoring the parsing state out of the main class such that a new parsing operation object is created on each invocation.
  • Refactor the parsing routines to be simpler to read and follow. The library has excellent support for the ISO date format standard, but is rather hard to follow.
  • Mark up the source code with Appledoc

Let me know if this is of interest to you and you'd be willing to merge such changes. I am also happy to help you with on-going maintenance of the library.

Use continuous integration

It'd be nice if we could set up something to automatically build and run the modern tests after each push.

Mentioned as part of #21.

stringFromDate: doesn't respect correct time zone offset in daylight savings

Hello,
I found out that stringFromDate doesn't respect time zone offset when date is in daylight savings time. For example, code:

    ISO8601DateFormatter * formatter = [[ISO8601DateFormatter alloc] init];
    formatter.defaultTimeZone = [NSTimeZone timeZoneWithName:@"Europe/Prague"];
    formatter.includeTime = YES;

    NSDate * date1 = [formatter dateFromString:@"2012-08-01T00:00:00+0200"];
    NSDate * date2 = [formatter dateFromString:@"2012-11-01T00:00:00+0100"];

    NSLog(@"1. Date 1: %@", date1); // just to be sure if date is OK
    NSLog(@"2. Date 2: %@", date2);

    NSLog(@"3. ISO8601 date 1 : %@", [formatter stringFromDate:date1]);
    NSLog(@"4. ISO8601 date 2 : %@", [formatter stringFromDate:date2]);

will produce wrong value at 3rd line:

1. Date 1: 2012-07-31 22:00:00 +0000
2. Date 2: 2012-10-31 23:00:00 +0000
3. ISO8601 date 1 : 2012-08-01T00:00:00+0100
4. ISO8601 date 2 : 2012-11-01T00:00:00+0100

I think that the fix is quite simple. You have to calculate GMT offset against the input date. Just change [timeZone secondsFromGMT] to [timeZone secondsFromGMTForDate:date];

Date From String returning wrong date with iOS 8

After updating to iOS8 I've noticed that all of my dates are now coming back with the wrong date and time. For example this is the date string that I get from a web service "2015-01-15T18:30:00-08:00" and when I use:

ISO8601DateFormatter *formatter = [ISO8601DateFormatter new];
NSDate *date = [formatter dateFromString:inputString];
NSLog(@"%@", date);

The log shows the date as "2015-01-16 02:30:00 +0000" and then getting just the time from this NSDate gives me 6:30PM instead of 10:30AM (which is used to show before I moved to iOS8).

I can't tell if it's something on my side or with iOS8 and the library so I just figured i would put it here for now. Thanks.

Time-only behavior is broken

Parsing a time-only string such as “T14:23-0800” will produce a string with the wrong date when the current local date is within the specified time zone offset from the next day UTC.

This is caused by #29. The underlying dateComponentsFromString: methods interpolate the current local date into the components, and dateFromString: then interprets those components in the specified time zone, creating a date that's a day too early (or, presumably, in some time zones, late).

Your blog is broken

Wasn't able to find an email address, lets try it this way.

Your blog gives an error:

Fatal error: __autoload() is no longer supported, use spl_autoload_register() instead in /home/public/blog/wp-includes/compat.php on line 502

https://boredzo.org/blog/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.