adium 5750:dad5f3048dc3: Update ISO8601 parsing to github.com/bo...
commits at adium.im
commits at adium.im
Thu Oct 31 03:30:17 UTC 2013
details: http://hg.adium.im/adium/rev/dad5f3048dc3
revision: 5750:dad5f3048dc3
branch: adium-1.5.9
author: Frank Dowsett <wixardy at adium.im>
date: Wed Oct 30 23:29:05 2013 -0400
Update ISO8601 parsing to github.com/boredzo/iso-8601-date-formatter/commit/40104f3 (v0.7). And like a7ca86f2f35c, this also removes all NSCalendarDates.
diffs (truncated from 3732 to 1000 lines):
diff -r 1521cab508bf -r dad5f3048dc3 Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj Wed Oct 30 18:34:07 2013 +0100
+++ b/Adium.xcodeproj/project.pbxproj Wed Oct 30 23:29:05 2013 -0400
@@ -208,8 +208,6 @@
318EA69C0D7A659900EDB105 /* TestColorAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 318EA69B0D7A659900EDB105 /* TestColorAdditions.m */; };
319B29800CE8EC6F00C65398 /* TestDateAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 319B297F0CE8EC6E00C65398 /* TestDateAdditions.m */; };
31A764B90DA572B8000AC729 /* AutoHyperlinks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3496A8EA07CE6CA30055BBAB /* AutoHyperlinks.framework */; };
- 31DDDA7112BDD5CE0048F6C0 /* scandate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31DDDA6F12BDD5CE0048F6C0 /* scandate.m */; };
- 31DDDA7A12BDD6E90048F6C0 /* TestScandate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31DDDA7912BDD6E90048F6C0 /* TestScandate.m */; };
31E0CD810C5EEF5200271DB1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31E0CD800C5EEF5200271DB1 /* CoreAudio.framework */; };
31FA804C0D4A8EB200ABE634 /* Adium.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 0CAC6A130C0C657A0090AE95 /* Adium.sdef */; };
3402D5A5080DBC91004E50B4 /* SortConfiguration.nib in Resources */ = {isa = PBXBuildFile; fileRef = 347E791D07CAA52300350507 /* SortConfiguration.nib */; };
@@ -247,7 +245,6 @@
3419DE7E0A81042F00C3FC68 /* remove.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 347E787507CA975900350507 /* remove.tiff */; };
3419DE7F0A81042F00C3FC68 /* msg-send-file.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 34D8326307CBD598006466F2 /* msg-send-file.tiff */; };
3419DE820A81042F00C3FC68 /* ToolbarPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 34D8327607CBD5B3006466F2 /* ToolbarPrefs.plist */; };
- 3419DF3B0A8119BF00C3FC68 /* AICalendarDate.m in Sources */ = {isa = PBXBuildFile; fileRef = 340D0A000A7DD1F40059A3AF /* AICalendarDate.m */; };
3419E2DF0A81445800C3FC68 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3419E2DE0A81445800C3FC68 /* Localizable.strings */; };
3419F7760531512200C68BA3 /* Adium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34BD9DE105314751000AB133 /* Adium.framework */; };
3419FE230531586A00C68BA3 /* Adium.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 34BD9DE105314751000AB133 /* Adium.framework */; };
@@ -1094,14 +1091,15 @@
5A5F601E12962ECE007A2232 /* AISegmentedControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A5F601912962D06007A2232 /* AISegmentedControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
5A5F8BBD12D560E400019727 /* AIDockNameOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A5F8BBC12D560E400019727 /* AIDockNameOverlay.m */; };
5A799674133C3D6F0005AC6A /* MessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5A1FEA601334549300C14951 /* MessageView.xib */; };
- 5A804FEA12BE9E84007CDC1B /* scandate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31DDDA6F12BDD5CE0048F6C0 /* scandate.m */; };
- 5A80508512BE9F00007CDC1B /* scandate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31DDDA6F12BDD5CE0048F6C0 /* scandate.m */; };
5A94397B1279ECB800FDD81D /* AIImgurImageUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A94397A1279ECB800FDD81D /* AIImgurImageUploader.m */; };
5A9A9F8911F2951400328DF9 /* AIDoNothingContactAlertPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A9A9F8811F2951400328DF9 /* AIDoNothingContactAlertPlugin.m */; };
5A9A9F8B11F295EB00328DF9 /* events-do-nothing.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 5A9A9F8A11F295EB00328DF9 /* events-do-nothing.tiff */; };
5AA2A0EE14B3EFF500B4DB65 /* AIOSCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AA2A0ED14B3EFF500B4DB65 /* AIOSCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; };
5AC423F3178CBD5100F5911A /* ChatCyclingDefaults-Old.plist in Resources */ = {isa = PBXBuildFile; fileRef = 34D7F1E815F85DD300F32F9B /* ChatCyclingDefaults-Old.plist */; };
5AC423F7178CBD5700F5911A /* ChatCyclingDefaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 34D7F1E915F85DD300F32F9B /* ChatCyclingDefaults.plist */; };
+ 5AD04C2C1821E8D3009801F8 /* ISO8601DateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AD04C2A1821E8D3009801F8 /* ISO8601DateFormatter.m */; };
+ 5AD04C2D1821E8D3009801F8 /* ISO8601DateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AD04C2B1821E8D3009801F8 /* ISO8601DateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5AD04C311821E910009801F8 /* ISO8601DateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AD04C2A1821E8D3009801F8 /* ISO8601DateFormatter.m */; };
5ADFFE5D133846C300069C1B /* keys.png in Resources */ = {isa = PBXBuildFile; fileRef = 5ADFFE5C133846C300069C1B /* keys.png */; };
6311F4710E340DD2004234B8 /* AISharedAdium.h in Headers */ = {isa = PBXBuildFile; fileRef = 6311F46F0E340DD2004234B8 /* AISharedAdium.h */; settings = {ATTRIBUTES = (Public, ); }; };
6311F4720E340DD2004234B8 /* AISharedAdium.m in Sources */ = {isa = PBXBuildFile; fileRef = 6311F4700E340DD2004234B8 /* AISharedAdium.m */; };
@@ -1299,10 +1297,6 @@
633400BC0F9C14C2003C77A9 /* AIWindowAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334FFF10F9C14C1003C77A9 /* AIWindowAdditions.m */; };
633400BF0F9C14C2003C77A9 /* OWAddressBookAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334FFF40F9C14C1003C77A9 /* OWAddressBookAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
633400C00F9C14C2003C77A9 /* OWAddressBookAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334FFF50F9C14C1003C77A9 /* OWAddressBookAdditions.m */; };
- 633400C10F9C14C2003C77A9 /* NSCalendarDate+ISO8601Parsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334FFF60F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 633400C20F9C14C2003C77A9 /* NSCalendarDate+ISO8601Parsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334FFF70F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.m */; };
- 633400C30F9C14C2003C77A9 /* NSCalendarDate+ISO8601Unparsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334FFF80F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 633400C40F9C14C2003C77A9 /* NSCalendarDate+ISO8601Unparsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334FFF90F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.m */; };
633400C50F9C14C2003C77A9 /* AIWindowControllerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334FFFA0F9C14C1003C77A9 /* AIWindowControllerAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
633400C60F9C14C2003C77A9 /* AIWindowControllerAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334FFFB0F9C14C1003C77A9 /* AIWindowControllerAdditions.m */; };
633400C70F9C14C2003C77A9 /* AIPasteboardAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334FFFC0F9C14C1003C77A9 /* AIPasteboardAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1326,7 +1320,6 @@
633D4FB70F9D30E3004F491E /* GetMetadataForFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 633D4FB10F9D30E3004F491E /* GetMetadataForFile.m */; };
633D4FB80F9D30E3004F491E /* GetMetadataForHTMLLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 633D4FB30F9D30E3004F491E /* GetMetadataForHTMLLog.m */; };
633D4FB90F9D30E3004F491E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 633D4FB40F9D30E3004F491E /* main.c */; };
- 633D4FBE0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 633D4FBD0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.m */; };
633D4FC20F9D3116004F491E /* schema.xml in Resources */ = {isa = PBXBuildFile; fileRef = 633D4FC00F9D3116004F491E /* schema.xml */; };
633D514F0F9D31BE004F491E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 633D50ED0F9D31BD004F491E /* InfoPlist.strings */; };
633D51500F9D31BE004F491E /* schema.strings in Resources */ = {isa = PBXBuildFile; fileRef = 633D50EF0F9D31BD004F491E /* schema.strings */; };
@@ -1952,10 +1945,6 @@
318EA69B0D7A659900EDB105 /* TestColorAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestColorAdditions.m; path = UnitTests/TestColorAdditions.m; sourceTree = "<group>"; };
319B29420CE8D28300C65398 /* TestDateAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestDateAdditions.h; path = UnitTests/TestDateAdditions.h; sourceTree = "<group>"; };
319B297F0CE8EC6E00C65398 /* TestDateAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestDateAdditions.m; path = UnitTests/TestDateAdditions.m; sourceTree = "<group>"; };
- 31DDDA6E12BDD5CE0048F6C0 /* scandate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scandate.h; path = Source/scandate.h; sourceTree = "<group>"; };
- 31DDDA6F12BDD5CE0048F6C0 /* scandate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = scandate.m; path = Source/scandate.m; sourceTree = "<group>"; };
- 31DDDA7812BDD6E90048F6C0 /* TestScandate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestScandate.h; path = UnitTests/TestScandate.h; sourceTree = "<group>"; };
- 31DDDA7912BDD6E90048F6C0 /* TestScandate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestScandate.m; path = UnitTests/TestScandate.m; sourceTree = "<group>"; };
31DDDAF112BDE54B0048F6C0 /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = "Other/Adium Spotlight Importer/Prefix.pch"; sourceTree = "<group>"; };
31E0CD800C5EEF5200271DB1 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
31E84DF10C7F387800674BCA /* AIUnitTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIUnitTestUtilities.h; path = UnitTests/AIUnitTestUtilities.h; sourceTree = "<group>"; };
@@ -2024,8 +2013,6 @@
340D03A80A7D798A0059A3AF /* AIControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIControllerProtocol.h"; sourceTree = "<group>"; };
340D081F0A7DBFE40059A3AF /* AIChatControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIChatControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIChatControllerProtocol.h"; sourceTree = "<group>"; };
340D083F0A7DC1540059A3AF /* AIContactAlertsControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIContactAlertsControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIContactAlertsControllerProtocol.h"; sourceTree = "<group>"; };
- 340D09FF0A7DD1F40059A3AF /* AICalendarDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AICalendarDate.h; path = Source/AICalendarDate.h; sourceTree = "<group>"; };
- 340D0A000A7DD1F40059A3AF /* AICalendarDate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AICalendarDate.m; path = Source/AICalendarDate.m; sourceTree = "<group>"; };
340D0D5B0A7E72030059A3AF /* AIContactControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIContactControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIContactControllerProtocol.h"; sourceTree = "<group>"; };
340D0D630A7E72DA0059A3AF /* AIContentControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIContentControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIContentControllerProtocol.h"; sourceTree = "<group>"; };
340D0D720A7E750E0059A3AF /* AIDockControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIDockControllerProtocol.h; path = "Frameworks/Adium Framework/Source/AIDockControllerProtocol.h"; sourceTree = "<group>"; };
@@ -4118,6 +4105,8 @@
5A9A9F8811F2951400328DF9 /* AIDoNothingContactAlertPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIDoNothingContactAlertPlugin.m; sourceTree = "<group>"; };
5A9A9F8A11F295EB00328DF9 /* events-do-nothing.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = "events-do-nothing.tiff"; path = "Resources/events-do-nothing.tiff"; sourceTree = SOURCE_ROOT; };
5AA2A0ED14B3EFF500B4DB65 /* AIOSCompatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIOSCompatibility.h; path = "Frameworks/AIUtilities Framework/Source/AIOSCompatibility.h"; sourceTree = "<group>"; };
+ 5AD04C2A1821E8D3009801F8 /* ISO8601DateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ISO8601DateFormatter.m; path = "Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.m"; sourceTree = "<group>"; };
+ 5AD04C2B1821E8D3009801F8 /* ISO8601DateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ISO8601DateFormatter.h; path = "Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.h"; sourceTree = "<group>"; };
5ADFFE5C133846C300069C1B /* keys.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = keys.png; path = Resources/keys.png; sourceTree = "<group>"; };
6311F46F0E340DD2004234B8 /* AISharedAdium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AISharedAdium.h; path = "Frameworks/Adium Framework/Source/AISharedAdium.h"; sourceTree = "<group>"; };
6311F4700E340DD2004234B8 /* AISharedAdium.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AISharedAdium.m; path = "Frameworks/Adium Framework/Source/AISharedAdium.m"; sourceTree = "<group>"; };
@@ -4316,10 +4305,6 @@
6334FFF30F9C14C1003C77A9 /* AIFontAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIFontAdditions.h; path = "Frameworks/AIUtilities Framework/Source/AIFontAdditions.h"; sourceTree = "<group>"; };
6334FFF40F9C14C1003C77A9 /* OWAddressBookAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWAddressBookAdditions.h; path = "Frameworks/AIUtilities Framework/Source/OWAddressBookAdditions.h"; sourceTree = "<group>"; };
6334FFF50F9C14C1003C77A9 /* OWAddressBookAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWAddressBookAdditions.m; path = "Frameworks/AIUtilities Framework/Source/OWAddressBookAdditions.m"; sourceTree = "<group>"; };
- 6334FFF60F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSCalendarDate+ISO8601Parsing.h"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.h"; sourceTree = "<group>"; };
- 6334FFF70F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSCalendarDate+ISO8601Parsing.m"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.m"; sourceTree = "<group>"; };
- 6334FFF80F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSCalendarDate+ISO8601Unparsing.h"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.h"; sourceTree = "<group>"; };
- 6334FFF90F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSCalendarDate+ISO8601Unparsing.m"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.m"; sourceTree = "<group>"; };
6334FFFA0F9C14C1003C77A9 /* AIWindowControllerAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIWindowControllerAdditions.h; path = "Frameworks/AIUtilities Framework/Source/AIWindowControllerAdditions.h"; sourceTree = "<group>"; };
6334FFFB0F9C14C1003C77A9 /* AIWindowControllerAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIWindowControllerAdditions.m; path = "Frameworks/AIUtilities Framework/Source/AIWindowControllerAdditions.m"; sourceTree = "<group>"; };
6334FFFC0F9C14C1003C77A9 /* AIPasteboardAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIPasteboardAdditions.h; path = "Frameworks/AIUtilities Framework/Source/AIPasteboardAdditions.h"; sourceTree = "<group>"; };
@@ -4333,8 +4318,6 @@
633D4FB30F9D30E3004F491E /* GetMetadataForHTMLLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GetMetadataForHTMLLog.m; path = "Other/Adium Spotlight Importer/GetMetadataForHTMLLog.m"; sourceTree = "<group>"; };
633D4FB40F9D30E3004F491E /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = "Other/Adium Spotlight Importer/main.c"; sourceTree = "<group>"; };
633D4FB50F9D30E3004F491E /* maintest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = maintest.m; path = "Other/Adium Spotlight Importer/maintest.m"; sourceTree = "<group>"; };
- 633D4FBC0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSCalendarDate+ISO8601Parsing.h"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.h"; sourceTree = "<group>"; };
- 633D4FBD0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSCalendarDate+ISO8601Parsing.m"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.m"; sourceTree = "<group>"; };
633D4FC00F9D3116004F491E /* schema.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = schema.xml; path = "Other/Adium Spotlight Importer/schema.xml"; sourceTree = "<group>"; };
633D4FC10F9D3116004F491E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "Other/Adium Spotlight Importer/Info.plist"; sourceTree = "<group>"; };
633D50550F9D31B8004F491E /* AdiumSpotlightImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AdiumSpotlightImporter.h; path = "Other/Adium Spotlight Importer/AdiumSpotlightImporter.h"; sourceTree = "<group>"; };
@@ -4396,7 +4379,6 @@
638392F609D4D67A0067B9B7 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Sparkle.framework; sourceTree = "<group>"; };
638BC1FA0FC932E000CE7600 /* AIObjectDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIObjectDebug.h; path = Source/AIObjectDebug.h; sourceTree = "<group>"; };
638BC1FB0FC932E000CE7600 /* AIObjectDebug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIObjectDebug.m; path = Source/AIObjectDebug.m; sourceTree = "<group>"; };
- 639DFB440F981C7C003C9A32 /* NSCalendarDate+ISO8601Parsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSCalendarDate+ISO8601Parsing.h"; path = "Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.h"; sourceTree = "<group>"; };
63A3A9670F9C35D3006C9CB0 /* AIUtilities_Framework.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AIUtilities_Framework.plist; sourceTree = "<group>"; };
63A3A9690F9C35D3006C9CB0 /* ca */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; };
63A3A96A0F9C35D3006C9CB0 /* cs */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -5166,8 +5148,6 @@
31FA7F100D4A75D000ABE634 /* TestRichTextCoercion.m */,
634BCD1D0DDC1542005AF1C2 /* TestMutableStringAdditions.h */,
634BCD1E0DDC1542005AF1C2 /* TestMutableStringAdditions.m */,
- 31DDDA7812BDD6E90048F6C0 /* TestScandate.h */,
- 31DDDA7912BDD6E90048F6C0 /* TestScandate.m */,
31034EFD0C8142680003F5AA /* TestStringAdditions.h */,
31034EFE0C8142680003F5AA /* TestStringAdditions.m */,
31034F0B0C8142720003F5AA /* UTF8Snowman.txt */,
@@ -5602,7 +5582,6 @@
3459CBE00A25FFA100ECC256 /* Log Indexing */ = {
isa = PBXGroup;
children = (
- 639DFB440F981C7C003C9A32 /* NSCalendarDate+ISO8601Parsing.h */,
3459CBEA0A25FFBE00ECC256 /* GetMetadataForHTMLLog.h */,
3459CBE90A25FFBE00ECC256 /* GetMetadataForHTMLLog.m */,
3459CBEC0A25FFBF00ECC256 /* AdiumSpotlightImporter.h */,
@@ -7174,8 +7153,6 @@
349B359E0A5F2231008BE092 /* Views and Cells */,
3456231F0A3771E100E7FC97 /* AIChatLog.h */,
3456231E0A3771E100E7FC97 /* AIChatLog.m */,
- 31DDDA6E12BDD5CE0048F6C0 /* scandate.h */,
- 31DDDA6F12BDD5CE0048F6C0 /* scandate.m */,
345623250A3771F400E7FC97 /* AILogToGroup.h */,
345623240A3771F300E7FC97 /* AILogToGroup.m */,
345623270A3771F400E7FC97 /* AILogFromGroup.h */,
@@ -7188,8 +7165,6 @@
34F849570A4AF04D0002A017 /* AILogFileUpgradeWindowController.m */,
34B5E25D0A7C94D3005186E6 /* AILogDateFormatter.h */,
34B5E25E0A7C94D3005186E6 /* AILogDateFormatter.m */,
- 340D09FF0A7DD1F40059A3AF /* AICalendarDate.h */,
- 340D0A000A7DD1F40059A3AF /* AICalendarDate.m */,
);
name = "Log Viewer";
sourceTree = "<group>";
@@ -7888,6 +7863,8 @@
6334FFA90F9C14C1003C77A9 /* Additions */ = {
isa = PBXGroup;
children = (
+ 5AD04C2A1821E8D3009801F8 /* ISO8601DateFormatter.m */,
+ 5AD04C2B1821E8D3009801F8 /* ISO8601DateFormatter.h */,
6334FFAC0F9C14C1003C77A9 /* AIApplicationAdditions.h */,
6334FFAD0F9C14C1003C77A9 /* AIApplicationAdditions.m */,
6334FFAE0F9C14C1003C77A9 /* AIArrayAdditions.h */,
@@ -7962,10 +7939,6 @@
6334FFF30F9C14C1003C77A9 /* AIFontAdditions.h */,
6334FFF40F9C14C1003C77A9 /* OWAddressBookAdditions.h */,
6334FFF50F9C14C1003C77A9 /* OWAddressBookAdditions.m */,
- 6334FFF60F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.h */,
- 6334FFF70F9C14C1003C77A9 /* NSCalendarDate+ISO8601Parsing.m */,
- 6334FFF80F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.h */,
- 6334FFF90F9C14C1003C77A9 /* NSCalendarDate+ISO8601Unparsing.m */,
6334FFFA0F9C14C1003C77A9 /* AIWindowControllerAdditions.h */,
6334FFFB0F9C14C1003C77A9 /* AIWindowControllerAdditions.m */,
6334FFFC0F9C14C1003C77A9 /* AIPasteboardAdditions.h */,
@@ -8024,8 +7997,6 @@
633D4FBB0F9D30FA004F491E /* External Sources */ = {
isa = PBXGroup;
children = (
- 633D4FBC0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.h */,
- 633D4FBD0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.m */,
);
name = "External Sources";
sourceTree = "<group>";
@@ -9147,6 +9118,7 @@
633400310F9C14C2003C77A9 /* AIDividedAlternatingRowOutlineView.h in Headers */,
633400330F9C14C2003C77A9 /* AIOutlineView.h in Headers */,
633400350F9C14C2003C77A9 /* AIAlternatingRowOutlineView.h in Headers */,
+ 5AD04C2D1821E8D3009801F8 /* ISO8601DateFormatter.h in Headers */,
633400370F9C14C2003C77A9 /* AIVariableHeightFlexibleColumnsOutlineView.h in Headers */,
633400390F9C14C2003C77A9 /* AIVariableHeightOutlineView.h in Headers */,
6334003B0F9C14C2003C77A9 /* AIMultiCellOutlineView.h in Headers */,
@@ -9200,8 +9172,6 @@
633400B90F9C14C2003C77A9 /* AIViewAdditions.h in Headers */,
633400BB0F9C14C2003C77A9 /* AIWindowAdditions.h in Headers */,
633400BF0F9C14C2003C77A9 /* OWAddressBookAdditions.h in Headers */,
- 633400C10F9C14C2003C77A9 /* NSCalendarDate+ISO8601Parsing.h in Headers */,
- 633400C30F9C14C2003C77A9 /* NSCalendarDate+ISO8601Unparsing.h in Headers */,
633400C50F9C14C2003C77A9 /* AIWindowControllerAdditions.h in Headers */,
633400C70F9C14C2003C77A9 /* AIPasteboardAdditions.h in Headers */,
633400D00F9C14E0003C77A9 /* AIUtilities.framework_Prefix.pch in Headers */,
@@ -9979,8 +9949,6 @@
318EA69C0D7A659900EDB105 /* TestColorAdditions.m in Sources */,
634BCD1F0DDC1542005AF1C2 /* TestMutableStringAdditions.m in Sources */,
3107D5250F63134F0051DDD5 /* TestAttributedStringAdditions.m in Sources */,
- 31DDDA7112BDD5CE0048F6C0 /* scandate.m in Sources */,
- 31DDDA7A12BDD6E90048F6C0 /* TestScandate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -10360,7 +10328,6 @@
34DC88810A7EEE2F003E1636 /* AdiumSpeech.m in Sources */,
34DC88840A7EEE2F003E1636 /* AdiumIdleManager.m in Sources */,
34DC88880A7EEE2F003E1636 /* XtrasInstaller.m in Sources */,
- 3419DF3B0A8119BF00C3FC68 /* AICalendarDate.m in Sources */,
34DC12FC0A81415D00D710F3 /* ESApplescriptabilityController.m in Sources */,
34DC13040A81417600D710F3 /* AILoginWindowController.m in Sources */,
C44BA7830AAB696400C7504F /* SetupAssistantBoxBackgroundView.m in Sources */,
@@ -10436,7 +10403,6 @@
76C1AF9C125A906A00D269A9 /* AIAdiumURLProtocol.m in Sources */,
5A94397B1279ECB800FDD81D /* AIImgurImageUploader.m in Sources */,
349062A2127F7E6900FC313F /* AITemporaryIRCAccountWindowController.m in Sources */,
- 5A80508512BE9F00007CDC1B /* scandate.m in Sources */,
1154F50B12E1476900B8CA27 /* AILogByAccountWindowController.m in Sources */,
766ABAB61306D1020049FFB7 /* AIUnreadMessagesTooltip.m in Sources */,
5A5F8BBD12D560E400019727 /* AIDockNameOverlay.m in Sources */,
@@ -10615,6 +10581,7 @@
6334007A0F9C14C2003C77A9 /* AIArrayAdditions.m in Sources */,
6334007C0F9C14C2003C77A9 /* AIAttributedStringAdditions.m in Sources */,
6334007E0F9C14C2003C77A9 /* AIBezierPathAdditions.m in Sources */,
+ 5AD04C2C1821E8D3009801F8 /* ISO8601DateFormatter.m in Sources */,
633400800F9C14C2003C77A9 /* AIBundleAdditions.m in Sources */,
633400820F9C14C2003C77A9 /* AICharacterSetAdditions.m in Sources */,
633400840F9C14C2003C77A9 /* AIColorAdditions.m in Sources */,
@@ -10647,8 +10614,6 @@
633400BA0F9C14C2003C77A9 /* AIViewAdditions.m in Sources */,
633400BC0F9C14C2003C77A9 /* AIWindowAdditions.m in Sources */,
633400C00F9C14C2003C77A9 /* OWAddressBookAdditions.m in Sources */,
- 633400C20F9C14C2003C77A9 /* NSCalendarDate+ISO8601Parsing.m in Sources */,
- 633400C40F9C14C2003C77A9 /* NSCalendarDate+ISO8601Unparsing.m in Sources */,
633400C60F9C14C2003C77A9 /* AIWindowControllerAdditions.m in Sources */,
633400C80F9C14C2003C77A9 /* AIPasteboardAdditions.m in Sources */,
63BB1CC90F9EDDB600424B80 /* AISharedWriterQueue.m in Sources */,
@@ -10663,11 +10628,10 @@
buildActionMask = 2147483647;
files = (
633D4FB60F9D30E3004F491E /* GetMetadataForHTMLLog-Additions.m in Sources */,
+ 5AD04C311821E910009801F8 /* ISO8601DateFormatter.m in Sources */,
633D4FB70F9D30E3004F491E /* GetMetadataForFile.m in Sources */,
633D4FB80F9D30E3004F491E /* GetMetadataForHTMLLog.m in Sources */,
633D4FB90F9D30E3004F491E /* main.c in Sources */,
- 633D4FBE0F9D30FA004F491E /* NSCalendarDate+ISO8601Parsing.m in Sources */,
- 5A804FEA12BE9E84007CDC1B /* scandate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff -r 1521cab508bf -r dad5f3048dc3 Frameworks/AIUtilities Framework/Source/AIDateAdditions.h
--- a/Frameworks/AIUtilities Framework/Source/AIDateAdditions.h Wed Oct 30 18:34:07 2013 +0100
+++ b/Frameworks/AIUtilities Framework/Source/AIDateAdditions.h Wed Oct 30 23:29:05 2013 -0400
@@ -36,4 +36,6 @@
minutes:(out NSInteger *)outMinutes
seconds:(out NSTimeInterval *)outSeconds;
++ (BOOL)isDate:(NSDate *)date1 sameDayAsDate:(NSDate *)date2;
+
@end
diff -r 1521cab508bf -r dad5f3048dc3 Frameworks/AIUtilities Framework/Source/AIDateAdditions.m
--- a/Frameworks/AIUtilities Framework/Source/AIDateAdditions.m Wed Oct 30 18:34:07 2013 +0100
+++ b/Frameworks/AIUtilities Framework/Source/AIDateAdditions.m Wed Oct 30 23:29:05 2013 -0400
@@ -42,4 +42,15 @@
if (outWeeks) *outWeeks = workInterval;
}
++ (BOOL)isDate:(NSDate *)date1 sameDayAsDate:(NSDate *)date2
+{
+ NSCalendar *calendar = [NSCalendar currentCalendar];
+
+ unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
+ NSDateComponents *comp1 = [calendar components:unitFlags fromDate:date1];
+ NSDateComponents *comp2 = [calendar components:unitFlags fromDate:date2];
+
+ return (comp1.day == comp2.day && comp1.month == comp2.month && comp1.year == comp2.year);
+}
+
@end
diff -r 1521cab508bf -r dad5f3048dc3 Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.h Wed Oct 30 23:29:05 2013 -0400
@@ -0,0 +1,209 @@
+/*ISO8601DateFormatter.h
+ *
+ *Created by Peter Hosey on 2009-04-11.
+ *Copyright 2009–2013 Peter Hosey. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+///Which of ISO 8601's three date formats the formatter should produce.
+typedef NS_ENUM(NSUInteger, ISO8601DateFormat) {
+ ///YYYY-MM-DD.
+ ISO8601DateFormatCalendar,
+ ///YYYY-DDD, where DDD ranges from 1 to 366; for example, 2009-32 is 2009-02-01.
+ ISO8601DateFormatOrdinal,
+ ///YYYY-Www-D, where ww ranges from 1 to 53 (the 'W' is literal) and D ranges from 1 to 7; for example, 2009-W05-07.
+ ISO8601DateFormatWeek,
+};
+
+///The default separator for time values. Currently, this is ':'.
+extern const unichar ISO8601DefaultTimeSeparatorCharacter;
+
+/*!
+ * @brief This class converts dates to and from ISO 8601 strings.
+ *
+ * @details TL;DR: You want to use ISO 8601 for any and all dates you send or receive over the internet, unless the spec for the protocol or format you're working with specifically tells you otherwise. See http://xkcd.com/1179/ .
+ *
+ * ISO 8601 is most recognizable as “year-month-date” strings, such as “2013-09-08T15:06:11-0800”. Of course, as you might expect of a formal standard, it's more sophisticated (some might say complicated) than that.
+ *
+ * For one thing, ISO 8601 actually defines *three* different date formats. The most common one, shown above, is called the calendar date format. The other two are week dates, where the month is replaced by a week of the year and the day is a day-of-the-week (1 being Monday) rather than day-of-month, and ordinal dates, where the middle segment is dispensed with entirely and the day component is day-of-year (1–366).
+ *
+ * The week format is the most bizarre of them, since 7 × 52 ≠ 365. The start and end of the year for purposes of week dates usually don't line up with the start and end of the calendar year. As a result, the first and/or last day of a year in the week-date “calendar” more often than not is on a different year from the first and/or last day of that year on the actual Gregorian calendar.
+ *
+ * In practice, almost all ISO 8601 dates you see in the wild will be in the calendar format.
+ *
+ * At any rate, this formatter can both parse and unparse dates in all three formats. (By “unparse”, I mean “produce a string from”—the reverse of parsing.)
+ *
+ * For a good and more detailed introduction to ISO 8601, see [“A summary of the international standard date and time notation” by Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/iso-time.html). The actual standard itself can be found in PDF format online with a well-crafted web search.
+ */
+
+ at interface ISO8601DateFormatter: NSFormatter
+
+ at property(nonatomic, retain) NSTimeZone *defaultTimeZone;
+
+#pragma mark Parsing
+/*!
+ * @name Parsing
+ */
+
+//As a formatter, this object converts strings to dates.
+
+/*!
+ * @brief Disables various leniencies in how the formatter parses strings.
+ *
+ * @details By default, the parser allows these extensions to the ISO 8601 standard:
+ *
+ * - Whitespace is allowed before the date.
+ * - Numbers don't have to be within range for a component. For example, you can have a string that refers to the 56th day of the hundredth month.
+ * - Since 0.6, allows a single whitespace character before the time-zone specification. This extension provides compatibility with NSDate output (`description`) and input (`dateWithString:`).
+ * - “Superfluous” hyphens in date specifications such as “`--DDD`” (where DDD is an ordinal day-of-year number and the year is implied) are allowed. (The standard recommends writing such a date as “`-DDD`”, with only a single hyphen. This is consistent with ordinal dates having only two components: the year and the day-of-year, separated by one hyphen.)
+ * - The same goes for week dates such as “`--Www-DD`”. Again, the extra hyphen really is superfluous, but is allowed as an extension.
+ * - Calendar dates with no separator between month and day-of-month are allowed, at least when they total four digits. (For example, 2013-0908, which would be interpreted as 2013-09-08.)
+ * - Single-digit components are allowed. (If you wish to specify a date in a single-digit year with the strict parser, pad it with zeroes.)
+ * - “YYYY-W” (without a week number after the 'W') is allowed, interpreted as “YYYY-W01-01”.
+ *
+ * Setting this property to `YES` will disable all of those extensions.
+ *
+ * These extensions are intended to help you process degenerate input (received from programs and services that use broken date-formatting libraries); whenever *you* create ISO 8601 strings, you should generate strictly-conforming ones.
+ *
+ * This property does not affect unparsing. The formatter always creates valid ISO 8601 strings. Any invalid string (loosely, any string that would require turning this property off to re-parse) should be considered a bug; please report it.
+ */
+ at property BOOL parsesStrictly;
+
+/*!
+ * @brief Parse a string into individual date components.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @returns An NSDateComponents object containing most of the information parsed from the string, aside from the fraction of second and time zone (which are lost).
+ * @sa dateComponentsFromString:timeZone:
+ * @sa dateComponentsFromString:timeZone:range:fractionOfSecond:
+ */
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string;
+/*!
+ * @brief Parse a string into individual date components.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @param outTimeZone If non-`NULL`, an NSTimeZone object or `nil` will be stored here, depending on whether the string specified a time zone.
+ * @returns An NSDateComponents object containing most of the information parsed from the string, aside from the fraction of second (which is lost) and time zone.
+ * @sa dateComponentsFromString:
+ * @sa dateComponentsFromString:timeZone:range:fractionOfSecond:
+ */
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone;
+/*!
+ * @brief Parse a string into individual date components.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @param outTimeZone If non-`NULL`, an NSTimeZone object or `nil` will be stored here, depending on whether the string specified a time zone.
+ * @param outRange If non-`NULL`, an NSRange structure will be stored here, identifying the substring of `string` that specified the date.
+ * @param outFractionOfSecond If non-`NULL`, an NSTimeInterval value will be stored here, containing the fraction of a second, if the string specified one. If it didn't, this will be set to zero.
+ * @returns An NSDateComponents object containing most of the information parsed from the string, aside from the fraction of second and time zone.
+ * @sa dateComponentsFromString:
+ * @sa dateComponentsFromString:timeZone:
+ */
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange fractionOfSecond:(NSTimeInterval *)outFractionOfSecond;
+
+/*!
+ * @brief Parse a string.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @returns An NSDate object containing most of the information parsed from the string, aside from the time zone (which is lost).
+ * @sa dateComponentsFromString:
+ * @sa dateFromString:timeZone:
+ * @sa dateFromString:timeZone:range:
+ */
+- (NSDate *) dateFromString:(NSString *)string;
+/*!
+ * @brief Parse a string.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @param outTimeZone If non-`NULL`, an NSTimeZone object or `nil` will be stored here, depending on whether the string specified a time zone.
+ * @returns An NSDate object containing most of the information parsed from the string, aside from the time zone.
+ * @sa dateComponentsFromString:timeZone:
+ * @sa dateFromString:
+ * @sa dateFromString:timeZone:range:
+ */
+- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone;
+/*!
+ * @brief Parse a string into a single date, identified by an NSDate object.
+ *
+ * @param string The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @param outTimeZone If non-`NULL`, an NSTimeZone object or `nil` will be stored here, depending on whether the string specified a time zone.
+ * @param outRange If non-`NULL`, an NSRange structure will be stored here, identifying the substring of `string` that specified the date.
+ * @returns An NSDate object containing most of the information parsed from the string, aside from the time zone.
+ * @sa dateComponentsFromString:timeZone:range:fractionOfSecond:
+ * @sa dateFromString:
+ * @sa dateFromString:timeZone:
+ */
+- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange;
+
+#pragma mark Unparsing
+/*!
+ * @name Unparsing
+ */
+
+/*!
+ * @brief Which ISO 8601 format to format dates in.
+ *
+ * @details See ISO8601DateFormat for possible values.
+ */
+ at property ISO8601DateFormat format;
+/*!
+ * @brief Whether strings should include time of day.
+ *
+ * @details If `NO`, strings include only the date, nothing after it.
+ *
+ * @sa timeSeparator
+ * @sa timeZoneSeparator
+ */
+ at property BOOL includeTime;
+/*!
+ * @brief The character to use to separate components of the time of day.
+ *
+ * @details This is used in both parsing and unparsing.
+ *
+ * The default value is ISO8601DefaultTimeSeparatorCharacter.
+ *
+ * When parsesStrictly is set to `YES`, this property is ignored. Otherwise, the parser will raise an exception if this is set to zero.
+ *
+ * @sa includeTime
+ * @sa timeZoneSeparator
+ */
+ at property unichar timeSeparator;
+/*!
+ * @brief The character to use to separate the hour and minute in a time zone specification.
+ *
+ * @details This is used in both parsing and unparsing.
+ *
+ * If zero, no separator is inserted into time zone specifications.
+ *
+ * The default value is zero (no separator).
+ *
+ * @sa includeTime
+ * @sa timeSeparator
+ */
+ at property unichar timeZoneSeparator;
+
+/*!
+ * @brief Produce a string that represents a date in UTC.
+ *
+ * @param date The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @returns A string that represents the date in UTC.
+ * @sa stringFromDate:timeZone:
+ */
+- (NSString *) stringFromDate:(NSDate *)date;
+/*!
+ * @brief Produce a string that represents a date.
+ *
+ * @param date The string to parse. Must represent a date in one of the ISO 8601 formats.
+ * @param timeZone An NSTimeZone object identifying the time zone in which to specify the date.
+ * @returns A string that represents the date in the requested time zone, if possible.
+ *
+ * @details Not all dates are representable in all time zones (because of historical calendar changes, such as transitions from the Julian to the Gregorian calendar).
+ * For an example, see http://stackoverflow.com/questions/18663407/date-formatter-returns-nil-for-june .
+ * This method *should* return `nil` in such cases.
+ *
+ * @sa stringFromDate:
+ */
+- (NSString *) stringFromDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone;
+
+ at end
diff -r 1521cab508bf -r dad5f3048dc3 Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.m
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.m Wed Oct 30 23:29:05 2013 -0400
@@ -0,0 +1,1008 @@
+/*ISO8601DateFormatter.m
+ *
+ *Created by Peter Hosey on 2009-04-11.
+ *Copyright 2009–2013 Peter Hosey. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+#if TARGET_OS_IPHONE
+# import <UIKit/UIKit.h>
+#endif
+#import "ISO8601DateFormatter.h"
+
+#ifndef DEFAULT_TIME_SEPARATOR
+# define DEFAULT_TIME_SEPARATOR ':'
+#endif
+const unichar ISO8601DefaultTimeSeparatorCharacter = DEFAULT_TIME_SEPARATOR;
+
+//Unicode date formats.
+#define ISO_CALENDAR_DATE_FORMAT @"yyyy-MM-dd"
+//#define ISO_WEEK_DATE_FORMAT @"YYYY-'W'ww-ee" //Doesn't actually work because NSDateComponents counts the weekday starting at 1.
+#define ISO_ORDINAL_DATE_FORMAT @"yyyy-DDD"
+#define ISO_TIME_FORMAT @"HH:mm:ss"
+//printf formats.
+#define ISO_TIMEZONE_UTC_FORMAT @"Z"
+#define ISO_TIMEZONE_OFFSET_FORMAT_NO_SEPARATOR @"%+.2d%.2d"
+#define ISO_TIMEZONE_OFFSET_FORMAT_WITH_SEPARATOR @"%+.2d%C%.2d"
+
+ at interface ISO8601DateFormatter ()
++ (void) createGlobalCachesThatDoNotAlreadyExist;
+//Used when a memory warning occurs (if at least one ISO 8601 Date Formatter exists at the time).
++ (void) purgeGlobalCaches;
+ at end
+
+ at interface ISO8601DateFormatter(UnparsingPrivate)
+
+- (NSString *) replaceColonsInString:(NSString *)timeFormat withTimeSeparator:(unichar)timeSep;
+
+- (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone;
+- (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone;
+
+ at end
+
+static NSMutableDictionary *timeZonesByOffset;
+
+#if ISO8601_TESTING_PURPOSES_ONLY
+//This method only exists for use by the project's test cases. DO NOT use this in an application.
+extern bool ISO8601DateFormatter_GlobalCachesAreWarm(void);
+
+bool ISO8601DateFormatter_GlobalCachesAreWarm(void) {
+ return (timeZonesByOffset != nil) && (timeZonesByOffset.count > 0);
+}
+#endif
+
+ at implementation ISO8601DateFormatter
+{
+ NSString *lastUsedFormatString;
+ NSDateFormatter *unparsingFormatter;
+
+ NSCalendar *parsingCalendar, *unparsingCalendar;
+
+ NSTimeZone *defaultTimeZone;
+ ISO8601DateFormat format;
+ unichar timeSeparator;
+ BOOL includeTime;
+ BOOL parsesStrictly;
+}
+
++ (void) initialize {
+ [self createGlobalCachesThatDoNotAlreadyExist];
+}
+
++ (void) createGlobalCachesThatDoNotAlreadyExist {
+ if (!timeZonesByOffset) {
+ timeZonesByOffset = [[NSMutableDictionary alloc] init];
+ }
+}
+
++ (void) purgeGlobalCaches {
+ NSMutableDictionary *oldCache = timeZonesByOffset;
+ timeZonesByOffset = nil;
+ [oldCache release];
+}
+
+- (NSCalendar *) makeCalendarWithDesiredConfiguration {
+ NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
+ calendar.firstWeekday = 2; //Monday
+ calendar.timeZone = [NSTimeZone defaultTimeZone];
+ return calendar;
+}
+
+- (id) init {
+ if ((self = [super init])) {
+ parsingCalendar = [[self makeCalendarWithDesiredConfiguration] retain];
+ unparsingCalendar = [[self makeCalendarWithDesiredConfiguration] retain];
+
+ format = ISO8601DateFormatCalendar;
+ timeSeparator = ISO8601DefaultTimeSeparatorCharacter;
+ includeTime = NO;
+ parsesStrictly = NO;
+
+#if TARGET_OS_IPHONE
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(didReceiveMemoryWarning:)
+ name:UIApplicationDidReceiveMemoryWarningNotification
+ object:nil];
+#endif
+ }
+ return self;
+}
+
+- (void) dealloc {
+#if TARGET_OS_IPHONE
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+#endif
+
+ [defaultTimeZone release];
+
+ [unparsingFormatter release];
+ [lastUsedFormatString release];
+ [parsingCalendar release];
+ [unparsingCalendar release];
+
+ [super dealloc];
+}
+
+- (void) didReceiveMemoryWarning:(NSNotification *)notification {
+ [[self class] purgeGlobalCaches];
+}
+
+ at synthesize defaultTimeZone;
+- (void) setDefaultTimeZone:(NSTimeZone *)tz {
+ if (defaultTimeZone != tz) {
+ [defaultTimeZone release];
+ defaultTimeZone = [tz retain];
+
+ unparsingCalendar.timeZone = defaultTimeZone;
+ }
+}
+
+//The following properties are only here because GCC doesn't like @synthesize in category implementations.
+
+#pragma mark Parsing
+
+ at synthesize parsesStrictly;
+
+static NSUInteger read_segment(const unichar *str, const unichar **next, NSUInteger *out_num_digits);
+static NSUInteger read_segment_4digits(const unichar *str, const unichar **next, NSUInteger *out_num_digits);
+static NSUInteger read_segment_2digits(const unichar *str, const unichar **next);
+static double read_double(const unichar *str, const unichar **next);
+static BOOL is_leap_year(NSUInteger year);
+
+/*Valid ISO 8601 date formats:
+ *
+ *YYYYMMDD
+ *YYYY-MM-DD
+ *YYYY-MM
+ *YYYY
+ *YY //century
+ * //Implied century: YY is 00-99
+ * YYMMDD
+ * YY-MM-DD
+ * -YYMM
+ * -YY-MM
+ * -YY
+ * //Implied year
+ * --MMDD
+ * --MM-DD
+ * --MM
+ * //Implied year and month
+ * ---DD
+ * //Ordinal dates: DDD is the number of the day in the year (1-366)
+ *YYYYDDD
+ *YYYY-DDD
+ * YYDDD
+ * YY-DDD
+ * -DDD
+ * //Week-based dates: ww is the number of the week, and d is the number (1-7) of the day in the week
+ *yyyyWwwd
+ *yyyy-Www-d
+ *yyyyWww
+ *yyyy-Www
+ *yyWwwd
+ *yy-Www-d
+ *yyWww
+ *yy-Www
+ * //Year of the implied decade
+ *-yWwwd
+ *-y-Www-d
+ *-yWww
+ *-y-Www
+ * //Week and day of implied year
+ * -Wwwd
+ * -Www-d
+ * //Week only of implied year
+ * -Www
+ * //Day only of implied week
+ * -W-d
+ */
+
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string {
+ return [self dateComponentsFromString:string timeZone:NULL];
+}
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone {
+ return [self dateComponentsFromString:string timeZone:outTimeZone range:NULL fractionOfSecond:NULL];
+}
+- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange fractionOfSecond:(out NSTimeInterval *)outFractionOfSecond {
+ if (string == nil)
+ return nil;
+ // Bail if the string contains a slash delimiter (we don't yet support ISO 8601 intervals and we don't support slash-separated dates)
+ if ([string rangeOfString:@"/"].location != NSNotFound)
+ return nil;
+
+ NSDate *now = [NSDate date];
+
+ NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
+ NSDateComponents *nowComponents = [parsingCalendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now];
+
+ NSUInteger
+ //Date
+ year,
+ month_or_week = 0U,
+ day = 0U,
+ //Time
+ hour = 0U;
+ NSTimeInterval
+ minute = 0.0,
+ second = 0.0;
+ //Time zone
+ NSInteger tz_hour = 0;
+ NSInteger tz_minute = 0;
+
+ enum {
+ monthAndDate,
+ week,
+ dateOnly
+ } dateSpecification = monthAndDate;
+
+ BOOL strict = self.parsesStrictly;
+ unichar timeSep = self.timeSeparator;
+
+ if (strict) timeSep = ISO8601DefaultTimeSeparatorCharacter;
+ NSAssert(timeSep != '\0', @"Time separator must not be NUL.");
+
+ BOOL isValidDate = ([string length] > 0U);
+ NSTimeZone *timeZone = nil;
+
+ const unichar *ch = (const unichar *)[string cStringUsingEncoding:NSUnicodeStringEncoding];
+
+ NSRange range = { 0U, 0U };
+ const unichar *start_of_date = NULL;
+ if (strict && isspace(*ch)) {
+ range.location = NSNotFound;
+ isValidDate = NO;
+ } else {
+ //Skip leading whitespace.
+ NSUInteger i = 0U;
+ while (isspace(ch[i]))
+ ++i;
+
+ range.location = i;
+ ch += i;
+ start_of_date = ch;
+
+ NSUInteger segment;
+ NSUInteger num_leading_hyphens = 0U, num_digits = 0U;
+
+ if (*ch == 'T') {
+ //There is no date here, only a time. Set the date to now; then we'll parse the time.
+ isValidDate = isdigit(*++ch);
+
+ year = nowComponents.year;
+ month_or_week = nowComponents.month;
+ day = nowComponents.day;
+ } else {
+ while(*ch == '-') {
+ ++num_leading_hyphens;
+ ++ch;
+ }
+
+ segment = read_segment(ch, &ch, &num_digits);
+ switch(num_digits) {
+ case 0:
+ if (*ch == 'W') {
+ if ((ch[1] == '-') && isdigit(ch[2]) && ((num_leading_hyphens == 1U) || ((num_leading_hyphens == 2U) && !strict))) {
+ year = nowComponents.year;
+ month_or_week = 1U;
+ ch += 2;
+ goto parseDayAfterWeek;
+ } else if (num_leading_hyphens == 1U) {
+ year = nowComponents.year;
+ goto parseWeekAndDay;
+ } else
+ isValidDate = NO;
+ } else
+ isValidDate = NO;
+ break;
+
+ case 8: //YYYY MM DD
+ if (num_leading_hyphens > 0U)
+ isValidDate = NO;
+ else {
+ day = segment % 100U;
+ segment /= 100U;
+ month_or_week = segment % 100U;
+ year = segment / 100U;
+ }
+ break;
+
+ case 6: //YYMMDD (implicit century)
+ if (num_leading_hyphens > 0U || strict)
+ isValidDate = NO;
+ else {
+ day = segment % 100U;
+ segment /= 100U;
+ month_or_week = segment % 100U;
+ year = nowComponents.year;
+ year -= (year % 100U);
+ year += segment / 100U;
+ }
+ break;
+
+ case 4:
+ switch(num_leading_hyphens) {
+ case 0: //YYYY
+ year = segment;
+
+ if (*ch == '-') ++ch;
+
+ if (!isdigit(*ch)) {
+ if (*ch == 'W')
+ goto parseWeekAndDay;
+ else
+ month_or_week = day = 1U;
+ } else {
+ segment = read_segment(ch, &ch, &num_digits);
+ switch(num_digits) {
+ case 4: //MMDD
+ if (strict)
+ isValidDate = NO;
+ else {
+ day = segment % 100U;
+ month_or_week = segment / 100U;
+ }
+ break;
+
+ case 2: //MM
+ month_or_week = segment;
+
+ if (*ch == '-') ++ch;
+ if (!isdigit(*ch))
+ day = 1U;
+ else
+ day = read_segment(ch, &ch, NULL);
+ break;
+
+ case 3: //DDD
+ day = segment % 1000U;
+ dateSpecification = dateOnly;
+ if (strict && (day > (365U + is_leap_year(year))))
+ isValidDate = NO;
+ break;
+
+ default:
+ isValidDate = NO;
+ }
+ }
+ break;
+
+ case 1: //YYMM
+ month_or_week = segment % 100U;
+ year = segment / 100U;
+
+ if (*ch == '-') ++ch;
+ if (!isdigit(*ch))
+ day = 1U;
+ else
+ day = read_segment(ch, &ch, NULL);
+
+ break;
+
+ case 2: //MMDD
+ day = segment % 100U;
+ month_or_week = segment / 100U;
+ year = nowComponents.year;
+
+ break;
+
+ default:
+ isValidDate = NO;
+ } //switch(num_leading_hyphens) (4 digits)
+ break;
+
+ case 1:
+ if (strict) {
+ //Two digits only - never just one.
+ if (num_leading_hyphens == 1U) {
+ if (*ch == '-') ++ch;
+ if (*++ch == 'W') {
+ year = nowComponents.year;
+ year -= (year % 10U);
+ year += segment;
+ goto parseWeekAndDay;
+ } else
+ isValidDate = NO;
+ } else
+ isValidDate = NO;
+ break;
+ }
+ case 2:
+ switch(num_leading_hyphens) {
+ case 0:
+ if (*ch == '-') {
+ //Implicit century
+ year = nowComponents.year;
+ year -= (year % 100U);
+ year += segment;
+
+ if (*++ch == 'W')
+ goto parseWeekAndDay;
+ else if (!isdigit(*ch)) {
+ goto centuryOnly;
+ } else {
+ //Get month and/or date.
+ segment = read_segment_4digits(ch, &ch, &num_digits);
+ NSLog(@"(%@) parsing month; segment is %lu and ch is %@", string, (unsigned long)segment, [NSString stringWithCString:(const char *)ch encoding:NSUnicodeStringEncoding]);
+ switch(num_digits) {
+ case 4: //YY-MMDD
+ day = segment % 100U;
+ month_or_week = segment / 100U;
+ break;
+
+ case 1: //YY-M; YY-M-DD (extension)
+ if (strict) {
+ isValidDate = NO;
+ break;
+ }
+ case 2: //YY-MM; YY-MM-DD
+ month_or_week = segment;
+ if (*ch == '-') {
+ if (isdigit(*++ch))
+ day = read_segment_2digits(ch, &ch);
+ else
+ day = 1U;
+ } else
+ day = 1U;
+ break;
+
+ case 3: //Ordinal date.
+ day = segment;
+ dateSpecification = dateOnly;
+ break;
+ }
+ }
+ } else if (*ch == 'W') {
+ year = nowComponents.year;
+ year -= (year % 100U);
+ year += segment;
+
+ parseWeekAndDay: //*ch should be 'W' here.
+ if (!isdigit(*++ch)) {
+ //Not really a week-based date; just a year followed by '-W'.
+ if (strict)
+ isValidDate = NO;
+ else
+ month_or_week = day = 1U;
+ } else {
+ month_or_week = read_segment_2digits(ch, &ch);
+ if (*ch == '-') ++ch;
+ parseDayAfterWeek:
+ day = isdigit(*ch) ? read_segment_2digits(ch, &ch) : 1U;
+ dateSpecification = week;
+ }
+ } else {
+ //Century only. Assume current year.
+ centuryOnly:
+ year = segment * 100U + nowComponents.year % 100U;
+ month_or_week = day = 1U;
+ }
+ break;
+
+ case 1:; //-YY; -YY-MM (implicit century)
+ NSLog(@"(%@) found %lu digits and one hyphen, so this is either -YY or -YY-MM; segment (year) is %lu", string, (unsigned long)num_digits, (unsigned long)segment);
+ NSUInteger current_year = nowComponents.year;
+ NSUInteger current_century = (current_year % 100U);
+ year = segment + (current_year - current_century);
+ if (num_digits == 1U) //implied decade
+ year += current_century - (current_year % 10U);
+
+ if (*ch == '-') {
+ ++ch;
+ month_or_week = read_segment_2digits(ch, &ch);
+ NSLog(@"(%@) month is %lu", string, (unsigned long)month_or_week);
+ }
+
+ day = 1U;
+ break;
+
+ case 2: //--MM; --MM-DD
+ year = nowComponents.year;
+ month_or_week = segment;
+ if (*ch == '-') {
+ ++ch;
+ day = read_segment_2digits(ch, &ch);
+ }
More information about the commits
mailing list