Update ISO8601 parsing to github.com/boredzo/iso-8601-date-formatter/commit/40104f3 (v0.7). And like a7ca86f2f35c, this also removes all NSCalendarDates. adium-1.5.9
authorFrank Dowsett <wixardy@adium.im>
Wed, 30 Oct 2013 23:29:05 -0400
branchadium-1.5.9
changeset 5750 dad5f3048dc3
parent 5749 1521cab508bf
child 5751 5fca6586773b
Update ISO8601 parsing to github.com/boredzo/iso-8601-date-formatter/commit/40104f3 (v0.7). And like a7ca86f2f35c, this also removes all NSCalendarDates.
Adium.xcodeproj/project.pbxproj
Frameworks/AIUtilities Framework/Source/AIDateAdditions.h
Frameworks/AIUtilities Framework/Source/AIDateAdditions.m
Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.h
Frameworks/AIUtilities Framework/Source/ISO8601DateFormatter.m
Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.h
Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.m
Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.h
Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.m
Frameworks/Adium Framework/Source/AIContentObject.m
Other/Adium Spotlight Importer/GetMetadataForFile.m
Other/Adium Spotlight Importer/GetMetadataForHTMLLog.m
Plugins/Error Message Handler/ErrorMessageHandlerPlugin.m
Plugins/Message Alias Support/AIMessageAliasPlugin.m
Plugins/Purple Service/CBPurpleOscarAccount.m
Source/AICalendarDate.h
Source/AICalendarDate.m
Source/AIChatLog.h
Source/AIChatLog.m
Source/AILogDateFormatter.m
Source/AILogViewerWindowController.h
Source/AILogViewerWindowController.m
Source/AILoggerPlugin.h
Source/AILoggerPlugin.m
Source/AIXMLChatlogConverter.h
Source/AIXMLChatlogConverter.m
Source/BGICLogImportController.m
Source/DCMessageContextDisplayPlugin.h
Source/DCMessageContextDisplayPlugin.m
Source/ESDebugController.m
Source/ESiTunesPlugin.m
Source/scandate.h
Source/scandate.m
UnitTests/TestScandate.h
UnitTests/TestScandate.m
--- 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;
 		};
--- 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
--- 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
--- /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.
+ */
+
+@interface ISO8601DateFormatter: NSFormatter
+
+@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.
+ */
+@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.
+ */
+@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
+ */
+@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
+ */
+@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
+ */
+@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;
+
+@end
--- /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"
+
+@interface ISO8601DateFormatter ()
++ (void) createGlobalCachesThatDoNotAlreadyExist;
+//Used when a memory warning occurs (if at least one ISO 8601 Date Formatter exists at the time).
++ (void) purgeGlobalCaches;
+@end
+
+@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;
+
+@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
+
+@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];
+}
+
+@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
+
+@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);
+							}
+							break;
+
+						case 3: //---DD
+							year = nowComponents.year;
+							month_or_week = nowComponents.month;
+							day = segment;
+							break;
+
+						default:
+							isValidDate = NO;
+					} //switch(num_leading_hyphens) (2 digits)
+					break;
+
+				case 7: //YYYY DDD (ordinal date)
+					if (num_leading_hyphens > 0U)
+						isValidDate = NO;
+					else {
+						day = segment % 1000U;
+						year = segment / 1000U;
+						dateSpecification = dateOnly;
+						if (strict && (day > (365U + is_leap_year(year))))
+							isValidDate = NO;
+					}
+					break;
+
+				case 3: //--DDD (ordinal date, implicit year)
+					//Technically, the standard only allows one hyphen. But it says that two hyphens is the logical implementation, and one was dropped for brevity. So I have chosen to allow the missing hyphen.
+					if ((num_leading_hyphens < 1U) || ((num_leading_hyphens > 2U) && !strict))
+						isValidDate = NO;
+					else {
+						day = segment;
+						year = nowComponents.year;
+						dateSpecification = dateOnly;
+						if (strict && (day > (365U + is_leap_year(year))))
+							isValidDate = NO;
+					}
+					break;
+
+				default:
+					isValidDate = NO;
+			}
+		}
+
+		if (isValidDate) {
+			if (isspace(*ch) || (*ch == 'T')) ++ch;
+
+			if (isdigit(*ch)) {
+				hour = read_segment_2digits(ch, &ch);
+				if (*ch == timeSep) {
+					++ch;
+					if ((timeSep == ',') || (timeSep == '.')) {
+						//We can't do fractional minutes when '.' is the segment separator.
+						//Only allow whole minutes and whole seconds.
+						minute = read_segment_2digits(ch, &ch);
+						if (*ch == timeSep) {
+							++ch;
+							second = read_segment_2digits(ch, &ch);
+						}
+					} else {
+						//Allow a fractional minute.
+						//If we don't get a fraction, look for a seconds segment.
+						//Otherwise, the fraction of a minute is the seconds.
+						minute = read_double(ch, &ch);
+						second = modf(minute, &minute);
+						if (second > DBL_EPSILON)
+							second *= 60.0; //Convert fraction (e.g. .5) into seconds (e.g. 30).
+						else if (*ch == timeSep) {
+							++ch;
+							second = read_double(ch, &ch);
+						}
+					}
+				}
+
+				if (!strict) {
+					if (isspace(*ch)) ++ch;
+				}
+
+				switch(*ch) {
+					case 'Z':
+						timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
+						++ch; //So that the Z is included in the range.
+						break;
+
+					case '+':
+					case '-':;
+						BOOL negative = (*ch == '-');
+						if (isdigit(*++ch)) {
+							//Read hour offset.
+							segment = *ch - '0';
+							if (isdigit(*++ch)) {
+								segment *= 10U;
+								segment += *(ch++) - '0';
+							}
+							tz_hour = (NSInteger)segment;
+							if (negative) tz_hour = -tz_hour;
+
+							//Optional separator.
+							if (*ch == self.timeZoneSeparator) ++ch;
+
+							if (isdigit(*ch)) {
+								//Read minute offset.
+								segment = *ch - '0';
+								if (isdigit(*++ch)) {
+									segment *= 10U;
+									segment += *ch - '0';
+								}
+								tz_minute = segment;
+								if (negative) tz_minute = -tz_minute;
+							}
+
+							[[self class] createGlobalCachesThatDoNotAlreadyExist];
+
+							NSInteger timeZoneOffset = (tz_hour * 3600) + (tz_minute * 60);
+							NSNumber *offsetNum = [NSNumber numberWithInteger:timeZoneOffset];
+							timeZone = [timeZonesByOffset objectForKey:offsetNum];
+							if (!timeZone) {
+								timeZone = [NSTimeZone timeZoneForSecondsFromGMT:timeZoneOffset];
+								if (timeZone)
+									[timeZonesByOffset setObject:timeZone forKey:offsetNum];
+							}
+						}
+				}
+			}
+		}
+
+		if (isValidDate) {
+			components.year = year;
+			components.day = day;
+			components.hour = hour;
+			components.minute = (NSInteger)minute;
+			components.second = (NSInteger)second;
+
+			if (outFractionOfSecond != NULL) {
+				NSTimeInterval fractionOfSecond = second - components.second;
+				if (fractionOfSecond > 0.0) {
+					*outFractionOfSecond = fractionOfSecond;
+				}
+			}
+
+			switch(dateSpecification) {
+				case monthAndDate:
+					components.month = month_or_week;
+					break;
+
+				case week:;
+					//Adapted from <http://personal.ecu.edu/mccartyr/ISOwdALG.txt>.
+					//This works by converting the week date into an ordinal date, then letting the next case handle it.
+					NSUInteger prevYear = year - 1U;
+					NSUInteger YY = prevYear % 100U;
+					NSUInteger C = prevYear - YY;
+					NSUInteger G = YY + YY / 4U;
+					NSUInteger isLeapYear = (((C / 100U) % 4U) * 5U);
+					NSUInteger Jan1Weekday = (isLeapYear + G) % 7U;
+					enum { monday, tuesday, wednesday, thursday/*, friday, saturday, sunday*/ };
+					components.day = ((8U - Jan1Weekday) + (7U * (Jan1Weekday > thursday))) + (day - 1U) + (7U * (month_or_week - 2));
+
+				case dateOnly: //An "ordinal date".
+					break;
+			}
+		}
+	} //if (!(strict && isdigit(ch[0])))
+
+	if (outRange) {
+		if (isValidDate)
+			range.length = ch - start_of_date;
+		else
+			range.location = NSNotFound;
+
+		*outRange = range;
+	}
+	if (outTimeZone) {
+		*outTimeZone = timeZone;
+	}
+
+	return isValidDate ? components : nil;
+}
+
+- (NSDate *) dateFromString:(NSString *)string {
+	return [self dateFromString:string timeZone:NULL];
+}
+- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone {
+	return [self dateFromString:string timeZone:outTimeZone range:NULL];
+}
+- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange {
+	NSTimeZone *timeZone = nil;
+	NSTimeInterval parsedFractionOfSecond = 0.0;
+  
+	NSDateComponents *components = [self dateComponentsFromString:string timeZone:&timeZone range:outRange fractionOfSecond:&parsedFractionOfSecond];
+
+	if (outTimeZone)
+		*outTimeZone = timeZone;
+	if (components == nil)
+		return nil;
+
+	parsingCalendar.timeZone = timeZone;
+
+	NSDate *parsedDate = [parsingCalendar dateFromComponents:components];
+
+	if (parsedFractionOfSecond > 0.0) {
+		parsedDate = [parsedDate dateByAddingTimeInterval:parsedFractionOfSecond];
+	}
+  
+  return parsedDate;
+}
+
+- (BOOL)getObjectValue:(id *)outValue forString:(NSString *)string errorDescription:(NSString **)error {
+	NSDate *date = [self dateFromString:string];
+	if (outValue)
+		*outValue = date;
+	return (date != nil);
+}
+
+#pragma mark Unparsing
+
+@synthesize format;
+@synthesize includeTime;
+@synthesize timeSeparator;
+
+- (NSString *) replaceColonsInString:(NSString *)timeFormat withTimeSeparator:(unichar)timeSep {
+	if (timeSep != ':') {
+		NSMutableString *timeFormatMutable = [[timeFormat mutableCopy] autorelease];
+		[timeFormatMutable replaceOccurrencesOfString:@":"
+		                               	   withString:[NSString stringWithCharacters:&timeSep length:1U]
+	                                      	  options:NSBackwardsSearch | NSLiteralSearch
+	                                        	range:(NSRange){ 0UL, [timeFormat length] }];
+		timeFormat = timeFormatMutable;
+	}
+	return timeFormat;
+}
+
+- (NSString *) stringFromDate:(NSDate *)date {
+	NSTimeZone *timeZone = self.defaultTimeZone;
+	if (!timeZone) timeZone = [NSTimeZone defaultTimeZone];
+	return [self stringFromDate:date timeZone:timeZone];
+}
+
+- (NSString *) stringFromDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone {
+	switch (self.format) {
+		case ISO8601DateFormatCalendar:
+			return [self stringFromDate:date formatString:ISO_CALENDAR_DATE_FORMAT timeZone:timeZone];
+		case ISO8601DateFormatWeek:
+			return [self weekDateStringForDate:date timeZone:timeZone];
+		case ISO8601DateFormatOrdinal:
+			return [self stringFromDate:date formatString:ISO_ORDINAL_DATE_FORMAT timeZone:timeZone];
+		default:
+			[NSException raise:NSInternalInconsistencyException format:@"self.format was %tu, not calendar (%tu), week (%tu), or ordinal (%tu)", self.format, ISO8601DateFormatCalendar, ISO8601DateFormatWeek, ISO8601DateFormatOrdinal];
+			return nil;
+	}
+}
+
+- (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone {
+	if (includeTime)
+		dateFormat = [dateFormat stringByAppendingFormat:@"'T'%@", [self replaceColonsInString:ISO_TIME_FORMAT withTimeSeparator:self.timeSeparator]];
+
+	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];
+	}
+
+	unparsingCalendar.timeZone = timeZone;
+	unparsingFormatter.timeZone = timeZone;
+	NSString *str = [unparsingFormatter stringForObjectValue:date];
+
+	if (includeTime) {
+		NSInteger offset = [timeZone secondsFromGMTForDate:date];
+		offset /= 60;  //bring down to minutes
+		if (offset == 0)
+			str = [str stringByAppendingString:ISO_TIMEZONE_UTC_FORMAT];
+		else {
+			int timeZoneOffsetHour = (int)(offset / 60);
+			int timeZoneOffsetMinute = (int)(offset % 60);
+			if (self.timeZoneSeparator)
+				str = [str stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT_WITH_SEPARATOR, timeZoneOffsetHour, self.timeZoneSeparator, timeZoneOffsetMinute];
+			else
+				str = [str stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT_NO_SEPARATOR, timeZoneOffsetHour, timeZoneOffsetMinute];
+		}
+	}
+
+	//Undo the change we made earlier
+	unparsingCalendar.timeZone = self.defaultTimeZone;
+	unparsingFormatter.timeZone = self.defaultTimeZone;
+
+	return str;
+}
+
+- (NSString *) stringForObjectValue:(id)value {
+	if ( ! [value isKindOfClass:[NSDate class]]) {
+		NSLog(@"%s: Can only format NSDate objects, not objects like %@", __func__, value);
+		return nil;
+	}
+
+	return [self stringFromDate:(NSDate *)value];
+}
+
+/*Adapted from:
+ *	Algorithm for Converting Gregorian Dates to ISO 8601 Week Date
+ *	Rick McCarty, 1999
+ *	http://personal.ecu.edu/mccartyr/ISOwdALG.txt
+ */
+- (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone {
+	unparsingCalendar.timeZone = timeZone;
+	NSDateComponents *components = [unparsingCalendar components:NSYearCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit fromDate:date];
+
+	//Determine the ordinal date.
+	NSDateComponents *startOfYearComponents = [unparsingCalendar components:NSYearCalendarUnit fromDate:date];
+	startOfYearComponents.month = 1;
+	startOfYearComponents.day = 1;
+	NSDateComponents *ordinalComponents = [unparsingCalendar components:NSDayCalendarUnit fromDate:[unparsingCalendar dateFromComponents:startOfYearComponents] toDate:date options:0];
+	ordinalComponents.day += 1;
+
+	enum {
+		monday, tuesday, wednesday, thursday, friday, saturday, sunday
+	};
+	enum {
+		january = 1, february, march,
+		april, may, june,
+		july, august, september,
+		october, november, december
+	};
+
+	NSInteger year = components.year;
+	NSInteger week = 0;
+	//The old unparser added 6 to [calendarDate dayOfWeek], which was zero-based; components.weekday is one-based, so we now add only 5.
+	NSInteger dayOfWeek = (components.weekday + 5) % 7;
+	NSInteger dayOfYear = ordinalComponents.day;
+
+	NSInteger prevYear = year - 1;
+
+	BOOL yearIsLeapYear = is_leap_year(year);
+	BOOL prevYearIsLeapYear = is_leap_year(prevYear);
+
+	NSInteger YY = prevYear % 100;
+	NSInteger C = prevYear - YY;
+	NSInteger G = YY + YY / 4;
+	NSInteger Jan1Weekday = (((((C / 100) % 4) * 5) + G) % 7);
+
+	NSInteger weekday = ((dayOfYear + Jan1Weekday) - 1) % 7;
+
+	if((dayOfYear <= (7 - Jan1Weekday)) && (Jan1Weekday > thursday)) {
+		week = 52 + ((Jan1Weekday == friday) || ((Jan1Weekday == saturday) && prevYearIsLeapYear));
+		--year;
+	} else {
+		NSInteger lengthOfYear = 365 + yearIsLeapYear;
+		if((lengthOfYear - dayOfYear) < (thursday - weekday)) {
+			++year;
+			week = 1;
+		} else {
+			NSInteger J = dayOfYear + (sunday - weekday) + Jan1Weekday;
+			week = J / 7 - (Jan1Weekday > thursday);
+		}
+	}
+
+	NSString *string = [NSString stringWithFormat:@"%lu-W%02lu-%02lu", (unsigned long)year, (unsigned long)week, ((unsigned long)dayOfWeek) + 1U];
+
+	NSString *timeString;
+	if(includeTime) {
+		NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+		unichar timeSep = self.timeSeparator;
+		if (!timeSep) timeSep = ISO8601DefaultTimeSeparatorCharacter;
+		formatter.dateFormat = [self replaceColonsInString:ISO_TIME_FORMAT withTimeSeparator:timeSep];
+		formatter.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
+		formatter.timeZone = timeZone;
+
+		timeString = [formatter stringForObjectValue:date];
+
+		[formatter release];
+
+		//TODO: This is copied from the calendar-date code. It should be isolated in a method.
+		NSInteger offset = [timeZone secondsFromGMTForDate:date];
+		offset /= 60;  //bring down to minutes
+		if (offset == 0)
+			timeString = [timeString stringByAppendingString:ISO_TIMEZONE_UTC_FORMAT];
+		else {
+			int timeZoneOffsetHour = (int)(offset / 60);
+			int timeZoneOffsetMinute = (int)(offset % 60);
+			if (self.timeZoneSeparator)
+				timeString = [timeString stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT_WITH_SEPARATOR,
+				                                                 timeZoneOffsetHour, self.timeZoneSeparator,
+				                                                 timeZoneOffsetMinute];
+			else
+				timeString = [timeString stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT_NO_SEPARATOR,
+				                                                 timeZoneOffsetHour, timeZoneOffsetMinute];
+		}
+
+		string = [string stringByAppendingFormat:@"T%@", timeString];
+	}
+
+	return string;
+}
+
+@end
+
+static NSUInteger read_segment(const unichar *str, const unichar **next, NSUInteger *out_num_digits) {
+	NSUInteger num_digits = 0U;
+	NSUInteger value = 0U;
+
+	while(isdigit(*str)) {
+		value *= 10U;
+		value += *str - '0';
+		++num_digits;
+		++str;
+	}
+
+	if (next) *next = str;
+	if (out_num_digits) *out_num_digits = num_digits;
+
+	return value;
+}
+static NSUInteger read_segment_4digits(const unichar *str, const unichar **next, NSUInteger *out_num_digits) {
+	NSUInteger num_digits = 0U;
+	NSUInteger value = 0U;
+
+	if (isdigit(*str)) {
+		value += *(str++) - '0';
+		++num_digits;
+	}
+
+	if (isdigit(*str)) {
+		value *= 10U;
+		value += *(str++) - '0';
+		++num_digits;
+	}
+
+	if (isdigit(*str)) {
+		value *= 10U;
+		value += *(str++) - '0';
+		++num_digits;
+	}
+
+	if (isdigit(*str)) {
+		value *= 10U;
+		value += *(str++) - '0';
+		++num_digits;
+	}
+
+	if (next) *next = str;
+	if (out_num_digits) *out_num_digits = num_digits;
+
+	return value;
+}
+static NSUInteger read_segment_2digits(const unichar *str, const unichar **next) {
+	NSUInteger value = 0U;
+
+	if (isdigit(*str))
+		value += *str - '0';
+
+	if (isdigit(*++str)) {
+		value *= 10U;
+		value += *(str++) - '0';
+	}
+
+	if (next) *next = str;
+
+	return value;
+}
+
+//strtod doesn't support ',' as a separator. This does.
+static double read_double(const unichar *str, const unichar **next) {
+	double value = 0.0;
+
+	if (str) {
+		NSUInteger int_value = 0;
+
+		while(isdigit(*str)) {
+			int_value *= 10U;
+			int_value += (*(str++) - '0');
+		}
+		value = int_value;
+
+		if (((*str == ',') || (*str == '.'))) {
+			++str;
+
+			register double multiplier, multiplier_multiplier;
+			multiplier = multiplier_multiplier = 0.1;
+
+			while(isdigit(*str)) {
+				value += (*(str++) - '0') * multiplier;
+				multiplier *= multiplier_multiplier;
+			}
+		}
+	}
+
+	if (next) *next = str;
+
+	return value;
+}
+
+static BOOL is_leap_year(NSUInteger year) {
+	return \
+	    ((year %   4U) == 0U)
+	&& (((year % 100U) != 0U)
+	||  ((year % 400U) == 0U));
+}
--- a/Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.h	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import <Foundation/Foundation.h>
-
-/*This addition parses ISO 8601 dates. A good introduction: <http://www.cl.cam.ac.uk/~mgk25/iso-time.html>
- *
- *Parsing can be done strictly, or not. When you parse loosely, leading whitespace is ignored, as is anything after the date.
- *The loose parser will return an NSCalendarDate for this string: @" \t\r\n\f\t  2006-03-02!!!"
- *Leading non-whitespace will not be ignored; the string will be rejected, and nil returned. See the README that came with this addition.
- *
- *The strict parser will only accept a string if the date is the entire string. The above string would be rejected immediately, solely on these grounds.
- *Also, the loose parser provides some extensions that the strict parser doesn't.
- *For example, the standard says for "-DDD" (an ordinal date in the implied year) that the logical representation (meaning, hierarchically) would be "--DDD", but because that extra hyphen is "superfluous", it was omitted.
- *The loose parser will accept the extra hyphen; the strict parser will not.
- *A full list of these extensions is in the README file.
- */
-
-//The default separator for time values. Currently, this is ':'.
-extern unichar ISO8601ParserDefaultTimeSeparatorCharacter;
-
-@interface NSCalendarDate(ISO8601Parsing)
-
-//This method is the one that does all the work. All the others are convenience methods.
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str strictly:(BOOL)strict getRange:(out NSRange *)outRange;
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str strictly:(BOOL)strict;
-
-//Strictly: NO.
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str timeSeparator:(unichar)timeSep getRange:(out NSRange *)outRange;
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str timeSeparator:(unichar)timeSep;
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str getRange:(out NSRange *)outRange;
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str;
-
-@end
--- a/Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Parsing.m	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,668 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import <ctype.h>
-#import <string.h>
-
-#import "NSCalendarDate+ISO8601Parsing.h"
-
-#ifndef DEFAULT_TIME_SEPARATOR
-#	define DEFAULT_TIME_SEPARATOR ':'
-#endif
-unichar ISO8601ParserDefaultTimeSeparatorCharacter = DEFAULT_TIME_SEPARATOR;
-
-static unsigned read_segment(const unsigned char *str, const unsigned char **next, unsigned *out_num_digits) {
-	unsigned num_digits = 0U;
-	unsigned value = 0U;
-
-	while(isdigit(*str)) {
-		value *= 10U;
-		value += *str - '0';
-		++num_digits;
-		++str;
-	}
-
-	if(next) *next = str;
-	if(out_num_digits) *out_num_digits = num_digits;
-
-	return value;
-}
-static unsigned read_segment_4digits(const unsigned char *str, const unsigned char **next, unsigned *out_num_digits) {
-	unsigned num_digits = 0U;
-	unsigned value = 0U;
-
-	if(isdigit(*str)) {
-		value += *(str++) - '0';
-		++num_digits;
-	}
-
-	if(isdigit(*str)) {
-		value *= 10U;
-		value += *(str++) - '0';
-		++num_digits;
-	}
-
-	if(isdigit(*str)) {
-		value *= 10U;
-		value += *(str++) - '0';
-		++num_digits;
-	}
-
-	if(isdigit(*str)) {
-		value *= 10U;
-		value += *(str++) - '0';
-		++num_digits;
-	}
-
-	if(next) *next = str;
-	if(out_num_digits) *out_num_digits = num_digits;
-
-	return value;
-}
-static unsigned read_segment_2digits(const unsigned char *str, const unsigned char **next) {
-	unsigned value = 0U;
-
-	if(isdigit(*str))
-		value += *str - '0';
-
-	if(isdigit(*++str)) {
-		value *= 10U;
-		value += *(str++) - '0';
-	}
-
-	if(next) *next = str;
-
-	return value;
-}
-
-//strtod doesn't support ',' as a separator. This does.
-static double read_double(const unsigned char *str, const unsigned char **next) {
-	double value = 0.0;
-
-	if(str) {
-		unsigned int_value = 0;
-
-		while(isdigit(*str)) {
-			int_value *= 10U;
-			int_value += (*(str++) - '0');
-		}
-		value = int_value;
-
-		if(((*str == ',') || (*str == '.'))) {
-			++str;
-
-			double multiplier, multiplier_multiplier;
-			multiplier = multiplier_multiplier = 0.1;
-
-			while(isdigit(*str)) {
-				value += (*(str++) - '0') * multiplier;
-				multiplier *= multiplier_multiplier;
-			}
-		}
-	}
-
-	if(next) *next = str;
-
-	return value;
-}
-
-static BOOL is_leap_year(NSInteger year) {
-	return \
-	    ((year %   4U) == 0U)
-	&& (((year % 100U) != 0U)
-	||  ((year % 400U) == 0U));
-}
-
-@implementation NSCalendarDate(ISO8601Parsing)
-
-/*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
- */
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str strictly:(BOOL)strict timeSeparator:(unichar)timeSep getRange:(out NSRange *)outRange {
-	if (!str || ![str length]) {
-		if (outRange) {
-			outRange->location = NSNotFound;
-			outRange->length = 0U;
-		}		
-
-		return nil;
-	}
-	
-	NSCalendarDate *now = [NSCalendarDate calendarDate];
-	NSUInteger
-		//Date
-		year = 0U,
-		month_or_week = 0U,
-		day = 0U,
-		//Time
-		hour = 0U;
-	NSTimeInterval
-		minute = 0.0,
-		second = 0.0;
-	//Time zone
-	signed tz_hour = 0;
-	signed tz_minute = 0;
-
-	enum {
-		monthAndDate,
-		week,
-		dateOnly
-	} dateSpecification = monthAndDate;
-
-	if(strict) timeSep = ISO8601ParserDefaultTimeSeparatorCharacter;
-	NSAssert(timeSep != '\0', @"Time separator must not be NUL.");
-
-	BOOL isValidDate = ([str length] > 0U);
-	NSTimeZone *timeZone = nil;
-	NSCalendarDate *date = nil;
-
-	const unsigned char *ch = (const unsigned char *)[str UTF8String];
-
-	NSRange range = { 0U, 0U };
-	const unsigned char *start_of_date = 0;
-	if (strict && isspace(*ch)) {
-		range.location = NSNotFound;
-		isValidDate = NO;
-	} else {
-		//Skip leading whitespace.
-		NSUInteger i = 0U;
-		for(NSInteger len = strlen((const char *)ch); i < len; ++i) {
-			if(!isspace(ch[i]))
-				break;
-		}
-
-		range.location = i;
-		ch += i;
-		start_of_date = ch;
-
-		unsigned segment;
-		unsigned 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 = [now yearOfCommonEra];
-			month_or_week = [now monthOfYear];
-			day = [now dayOfMonth];
-		} 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 = [now yearOfCommonEra];
-							month_or_week = 1U;
-							ch += 2;
-							goto parseDayAfterWeek;
-						} else if(num_leading_hyphens == 1U) {
-							year = [now yearOfCommonEra];
-							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)
-						isValidDate = NO;
-					else {
-						day = segment % 100U;
-						segment /= 100U;
-						month_or_week = segment % 100U;
-						year  = [now yearOfCommonEra];
-						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
-										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 > (365 + 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 = [now yearOfCommonEra];
-
-							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  = [now yearOfCommonEra];
-								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  = [now yearOfCommonEra];
-								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 %u and ch is %s", str, segment, ch);
-									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  = [now yearOfCommonEra];
-								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 + [now yearOfCommonEra] % 100U;
-								month_or_week = day = 1U;
-							}
-							break;
-
-						case 1:; //-YY; -YY-MM (implicit century)
-							NSLog(@"(%@) found %u digits and one hyphen, so this is either -YY or -YY-MM; segment (year) is %u", str, num_digits, segment);
-							NSInteger current_year = [now yearOfCommonEra];
-							NSInteger current_century = (current_year % 100);
-							year = segment + (current_year - century);
-							if(num_digits == 1U) //implied decade
-								year += current_century - (current_year % 10);
-
-							if(*ch == '-') {
-								++ch;
-								month_or_week = read_segment_2digits(ch, &ch);
-								NSLog(@"(%@) month is %lu", str, (unsigned long)month_or_week);
-							}
-
-							day = 1U;
-							break;
-
-						case 2: //--MM; --MM-DD
-							year = [now yearOfCommonEra];
-							month_or_week = segment;
-							if(*ch == '-') {
-								++ch;
-								day = read_segment_2digits(ch, &ch);
-							}
-							break;
-
-						case 3: //---DD
-							year = [now yearOfCommonEra];
-							month_or_week = [now monthOfYear];
-							day = segment;
-							break;
-
-						default:
-							isValidDate = NO;
-					} //switch(num_leading_hyphens) (2 digits)
-					break;
-
-				case 7: //YYYY DDD (ordinal date)
-					if(num_leading_hyphens > 0U)
-						isValidDate = NO;
-					else {
-						day = segment % 1000U;
-						year = segment / 1000U;
-						dateSpecification = dateOnly;
-						if(strict && (day > (365U + is_leap_year(year))))
-							isValidDate = NO;
-					}
-					break;
-
-				case 3: //--DDD (ordinal date, implicit year)
-					//Technically, the standard only allows one hyphen. But it says that two hyphens is the logical implementation, and one was dropped for brevity. So I have chosen to allow the missing hyphen.
-					if((num_leading_hyphens < 1U) || ((num_leading_hyphens > 2U) && !strict))
-						isValidDate = NO;
-					else {
-						day = segment;
-						year = [now yearOfCommonEra];
-						dateSpecification = dateOnly;
-						if(strict && (day > (365U + is_leap_year(year))))
-							isValidDate = NO;
-					}
-					break;
-
-				default:
-					isValidDate = NO;
-			}
-		}
-
-		if (isValidDate) {
-			if (isspace(*ch) || (*ch == 'T')) ++ch;
-
-			if (isdigit(*ch)) {
-				hour = read_segment_2digits(ch, &ch);
-				if(*ch == timeSep) {
-					++ch;
-					if((timeSep == ',') || (timeSep == '.')) {
-						//We can't do fractional minutes when '.' is the segment separator.
-						//Only allow whole minutes and whole seconds.
-						minute = read_segment_2digits(ch, &ch);
-						if(*ch == timeSep) {
-							++ch;
-							second = read_segment_2digits(ch, &ch);
-						}
-					} else {
-						//Allow a fractional minute.
-						//If we don't get a fraction, look for a seconds segment.
-						//Otherwise, the fraction of a minute is the seconds.
-						minute = read_double(ch, &ch);
-						second = modf(minute, &minute);
-						if(second > DBL_EPSILON)
-							second *= 60.0; //Convert fraction (e.g. .5) into seconds (e.g. 30).
-						else if(*ch == timeSep) {
-							++ch;
-							second = read_double(ch, &ch);
-						}
-					}
-				}
-
-				switch(*ch) {
-					case 'Z':
-						timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
-						break;
-
-					case '+':
-					case '-':;
-						BOOL negative = (*ch == '-');
-						if(isdigit(*++ch)) {
-							//Read hour offset.
-							segment = *ch - '0';
-							if(isdigit(*++ch)) {
-								segment *= 10U;
-								segment += *(ch++) - '0';
-							}
-							tz_hour = (signed)segment;
-							if(negative) tz_hour = -tz_hour;
-
-							//Optional separator.
-							if(*ch == timeSep) ++ch;
-
-							if(isdigit(*ch)) {
-								//Read minute offset.
-								segment = *ch - '0';
-								if(isdigit(*++ch)) {
-									segment *= 10U;
-									segment += *ch - '0';
-								}
-								tz_minute = segment;
-								if(negative) tz_minute = -tz_minute;
-							}
-
-							NSInteger secondsFromGMT = (tz_hour * 3600) + (tz_minute * 60);
-							static NSInteger lastUsedSecondsFromGMT = NSNotFound;
-							static NSTimeZone *lastUsedTimeZone;
-							if (secondsFromGMT == lastUsedSecondsFromGMT)
-								timeZone = [[lastUsedTimeZone retain] autorelease];
-							else
-								timeZone = [NSTimeZone timeZoneForSecondsFromGMT:secondsFromGMT];
-							lastUsedSecondsFromGMT = secondsFromGMT;
-							[lastUsedTimeZone autorelease];
-							lastUsedTimeZone = [timeZone retain];
-						}
-				}
-			}
-		}
-
-		if (isValidDate) {
-			switch (dateSpecification) {
-				case monthAndDate:
-					date = [NSCalendarDate dateWithYear:year
-												  month:month_or_week
-													day:day
-												   hour:hour
-												 minute:(NSUInteger)minute
-												 second:(NSUInteger)second
-											   timeZone:timeZone];
-					break;
-
-				case week:;
-					//Adapted from <http://personal.ecu.edu/mccartyr/ISOwdALG.txt>.
-					//This works by converting the week date into an ordinal date, then letting the next case handle it.
-					NSInteger prevYear = year - 1U;
-					NSInteger YY = prevYear % 100U;
-					NSInteger C = prevYear - YY;
-					NSInteger G = YY + YY / 4U;
-					NSInteger isLeapYear = (((C / 100U) % 4U) * 5U);
-					NSInteger Jan1Weekday = (isLeapYear + G) % 7U;
-					enum { monday, tuesday, wednesday, thursday/*, friday, saturday, sunday*/ };
-					day = ((8U - Jan1Weekday) + (7U * (Jan1Weekday > thursday))) + (day - 1U) + (7U * (month_or_week - 2));
-
-				case dateOnly: //An "ordinal date".
-					date = [NSCalendarDate dateWithYear:year
-												  month:1
-													day:1
-												   hour:hour
-												 minute:(NSUInteger)minute
-												 second:(NSUInteger)second
-											   timeZone:timeZone];
-					date = [date dateByAddingYears:0
-											months:0
-											  days:(day - 1)
-											 hours:0
-										   minutes:0
-										   seconds:0];
-					break;
-			}
-		}
-	} //if (!(strict && isdigit(ch[0])))
-
-	if(outRange) {
-		if(isValidDate)
-			range.length = ch - start_of_date;
-		else
-			range.location = NSNotFound;
-
-		*outRange = range;
-	}
-
-	return date;
-}
-
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str {
-	return [self calendarDateWithString:str strictly:NO getRange:NULL];
-}
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str strictly:(BOOL)strict {
-	return [self calendarDateWithString:str strictly:strict getRange:NULL];
-}
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str strictly:(BOOL)strict getRange:(out NSRange *)outRange {
-	return [self calendarDateWithString:str strictly:strict timeSeparator:ISO8601ParserDefaultTimeSeparatorCharacter getRange:NULL];
-}
-
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str timeSeparator:(unichar)timeSep getRange:(out NSRange *)outRange {
-	return [self calendarDateWithString:str strictly:NO timeSeparator:timeSep getRange:outRange];
-}
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str timeSeparator:(unichar)timeSep {
-	return [self calendarDateWithString:str strictly:NO timeSeparator:timeSep getRange:NULL];
-}
-+ (NSCalendarDate *)calendarDateWithString:(NSString *)str getRange:(out NSRange *)outRange {
-	return [self calendarDateWithString:str strictly:NO timeSeparator:ISO8601ParserDefaultTimeSeparatorCharacter getRange:outRange];
-}
-
-@end
--- a/Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.h	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import <Foundation/Foundation.h>
-
-/*This addition unparses dates to ISO 8601 strings. A good introduction to ISO 8601: <http://www.cl.cam.ac.uk/~mgk25/iso-time.html>
- */
-
-//The default separator for time values. Currently, this is ':'.
-extern unichar ISO8601UnparserDefaultTimeSeparatorCharacter;
-
-@interface NSCalendarDate(ISO8601Unparsing)
-
-- (NSString *)ISO8601DateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep;
-- (NSString *)ISO8601WeekDateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep;
-- (NSString *)ISO8601OrdinalDateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep;
-
-- (NSString *)ISO8601DateStringWithTime:(BOOL)includeTime;
-- (NSString *)ISO8601WeekDateStringWithTime:(BOOL)includeTime;
-- (NSString *)ISO8601OrdinalDateStringWithTime:(BOOL)includeTime;
-
-//includeTime: YES.
-- (NSString *)ISO8601DateStringWithTimeSeparator:(unichar)timeSep;
-- (NSString *)ISO8601WeekDateStringWithTimeSeparator:(unichar)timeSep;
-- (NSString *)ISO8601OrdinalDateStringWithTimeSeparator:(unichar)timeSep;
-
-//includeTime: YES.
-- (NSString *)ISO8601DateString;
-- (NSString *)ISO8601WeekDateString;
-- (NSString *)ISO8601OrdinalDateString;
-
-@end
-
--- a/Frameworks/AIUtilities Framework/Source/NSCalendarDate+ISO8601Unparsing.m	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import <Foundation/Foundation.h>
-
-#ifndef DEFAULT_TIME_SEPARATOR
-#	define DEFAULT_TIME_SEPARATOR ':'
-#endif
-unichar ISO8601UnparserDefaultTimeSeparatorCharacter = DEFAULT_TIME_SEPARATOR;
-
-static BOOL is_leap_year(NSInteger year) {
-	return \
-	    ((year %   4) == 0)
-	&& (((year % 100) != 0)
-	||  ((year % 400) == 0));
-}
-
-@interface NSString(ISO8601Unparsing)
-
-//Replace all occurrences of ':' with timeSep.
-- (NSString *)prepareDateFormatWithTimeSeparator:(unichar)timeSep;
-
-@end
-
-@implementation NSCalendarDate(ISO8601Unparsing)
-
-#pragma mark Public methods
-
-- (NSString *)ISO8601DateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep {
-	NSString *dateFormat = [(includeTime ? @"yyyy'-'MM'-'dd'T'HH':'mm':'ss" : @"yyyy'-'MM'-'dd") prepareDateFormatWithTimeSeparator:timeSep];
-	NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
-	formatter.dateFormat = dateFormat;
-	NSString *str = [formatter stringFromDate:self];
-	[formatter release];
-	if(includeTime) {
-		NSInteger offset = [[self timeZone] secondsFromGMT];
-		offset /= 60;  //bring down to minutes
-		if(offset == 0)
-			str = [str stringByAppendingString:@"Z"];
-		if(offset < 0)
-			str = [str stringByAppendingFormat:@"-%02d:%02d", -offset / 60, -offset % 60];
-		else
-			str = [str stringByAppendingFormat:@"+%02d:%02d", offset / 60, offset % 60];
-	}
-	return str;
-}
-/*Adapted from:
- *	Algorithm for Converting Gregorian Dates to ISO 8601 Week Date
- *	Rick McCarty, 1999
- *	http://personal.ecu.edu/mccartyr/ISOwdALG.txt
- */
-- (NSString *)ISO8601WeekDateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep {
-	enum {
-		monday, tuesday, wednesday, thursday, friday, saturday, sunday
-	};
-	enum {
-		january = 1U, february, march,
-		april, may, june,
-		july, august, september,
-		october, november, december
-	};
-
-	NSInteger year = [self yearOfCommonEra];
-	NSInteger week = 0;
-	NSInteger dayOfWeek = ([self dayOfWeek] + 6) % 7;
-	NSInteger dayOfYear = [self dayOfYear];
-
-	NSInteger prevYear = year - 1U;
-
-	BOOL yearIsLeapYear = is_leap_year(year);
-	BOOL prevYearIsLeapYear = is_leap_year(prevYear);
-
-	NSInteger YY = prevYear % 100;
-	NSInteger C = prevYear - YY;
-	NSInteger G = YY + YY / 4;
-	NSInteger Jan1Weekday = (((((C / 100) % 4) * 5) + G) % 7);
-
-	NSInteger weekday = ((dayOfYear + Jan1Weekday) - 1) % 7;
-
-	if((dayOfYear <= (7U - Jan1Weekday)) && (Jan1Weekday > thursday)) {
-		week = 52U + ((Jan1Weekday == friday) || ((Jan1Weekday == saturday) && prevYearIsLeapYear));
-		--year;
-	} else {
-		unsigned lengthOfYear = 365U + yearIsLeapYear;
-		if((lengthOfYear - dayOfYear) < (thursday - weekday)) {
-			++year;
-			week = 1U;
-		} else {
-			NSInteger J = dayOfYear + (sunday - weekday) + Jan1Weekday;
-			week = J / 7U - (Jan1Weekday > thursday);
-		}
-	}
-
-	NSString *timeString;
-	if(includeTime) {
-		NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
-		formatter.dateFormat = [@"'T'HH':'mm':'ssZ" prepareDateFormatWithTimeSeparator:timeSep];
-		timeString = [formatter stringForObjectValue:self];
-		[formatter release];
-	} else
-		timeString = @"";
-
-	return [NSString stringWithFormat:@"%u-W%02u-%02u%@", year, week, dayOfWeek + 1U, timeString];
-}
-- (NSString *)ISO8601OrdinalDateStringWithTime:(BOOL)includeTime timeSeparator:(unichar)timeSep {
-	NSString *timeString;
-	if(includeTime) {
-		NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
-		formatter.dateFormat = [@"'T'HH':'mm':'ssZ" prepareDateFormatWithTimeSeparator:timeSep];
-		timeString = [formatter stringForObjectValue:self];
-		[formatter release];
-	} else
-		timeString = @"";
-
-	return [NSString stringWithFormat:@"%u-%03u%@", [self yearOfCommonEra], [self dayOfYear], timeString];
-}
-
-#pragma mark -
-
-- (NSString *)ISO8601DateStringWithTime:(BOOL)includeTime {
-	return [self ISO8601DateStringWithTime:includeTime timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-- (NSString *)ISO8601WeekDateStringWithTime:(BOOL)includeTime {
-	return [self ISO8601WeekDateStringWithTime:includeTime timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-- (NSString *)ISO8601OrdinalDateStringWithTime:(BOOL)includeTime {
-	return [self ISO8601OrdinalDateStringWithTime:includeTime timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-
-#pragma mark -
-
-- (NSString *)ISO8601DateStringWithTimeSeparator:(unichar)timeSep {
-	return [self ISO8601DateStringWithTime:YES timeSeparator:timeSep];
-}
-- (NSString *)ISO8601WeekDateStringWithTimeSeparator:(unichar)timeSep {
-	return [self ISO8601WeekDateStringWithTime:YES timeSeparator:timeSep];
-}
-- (NSString *)ISO8601OrdinalDateStringWithTimeSeparator:(unichar)timeSep {
-	return [self ISO8601OrdinalDateStringWithTime:YES timeSeparator:timeSep];
-}
-
-#pragma mark -
-
-- (NSString *)ISO8601DateString {
-	return [self ISO8601DateStringWithTime:YES timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-- (NSString *)ISO8601WeekDateString {
-	return [self ISO8601WeekDateStringWithTime:YES timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-- (NSString *)ISO8601OrdinalDateString {
-	return [self ISO8601OrdinalDateStringWithTime:YES timeSeparator:ISO8601UnparserDefaultTimeSeparatorCharacter];
-}
-
-@end
-
-@implementation NSString(ISO8601Unparsing)
-
-//Replace all occurrences of ':' with timeSep.
-- (NSString *)prepareDateFormatWithTimeSeparator:(unichar)timeSep {
-	NSString *dateFormat = self;
-	if(timeSep != ':') {
-		NSMutableString *dateFormatMutable = [[dateFormat mutableCopy] autorelease];
-		[dateFormatMutable replaceOccurrencesOfString:@":"
-		                               	   withString:[NSString stringWithCharacters:&timeSep length:1U]
-	                                      	  options:NSBackwardsSearch | NSLiteralSearch
-	                                        	range:(NSRange){ 0U, [dateFormat length] }];
-		dateFormat = dateFormatMutable;
-	}
-	return dateFormat;
-}
-
-@end
--- a/Frameworks/Adium Framework/Source/AIContentObject.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Frameworks/Adium Framework/Source/AIContentObject.m	Wed Oct 30 23:29:05 2013 -0400
@@ -20,6 +20,7 @@
 #import <Adium/AIContentObject.h>
 #import <Adium/AIListObject.h>
 #import <Adium/AIHTMLDecoder.h>
+#import <AIUtilities/AIDateAdditions.h>
 
 @implementation AIContentObject
 
@@ -127,10 +128,9 @@
 //Content is from the same day. If passed nil, content is from the current day.
 - (BOOL)isFromSameDayAsContent:(AIContentObject *)inContent
 {
-	NSCalendarDate *ourDate = [[self date] dateWithCalendarFormat:nil timeZone:nil];
-	NSCalendarDate *inDate = [(inContent ? [inContent date] : [NSDate date]) dateWithCalendarFormat:nil timeZone:nil];
+	NSDate *inDate = inContent ? [inContent date] : [NSDate date];
 	
-	return [ourDate dayOfCommonEra] == [inDate dayOfCommonEra];
+	return [NSDate isDate:self.date sameDayAsDate:inDate];
 }
 
 //Content --------------------------------------------------------------------------------------------------------------
--- a/Other/Adium Spotlight Importer/GetMetadataForFile.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Other/Adium Spotlight Importer/GetMetadataForFile.m	Wed Oct 30 23:29:05 2013 -0400
@@ -16,7 +16,7 @@
 #import <CoreFoundation/CoreFoundation.h>
 #import <CoreServices/CoreServices.h> 
 #import "GetMetadataForHTMLLog.h"
-#import "NSCalendarDate+ISO8601Parsing.h"
+#import "ISO8601DateFormatter.h"
 
 /*
  Relevant keys from MDItem.h we use or may want to use:
@@ -213,19 +213,20 @@
 						   forKey:@"com_adiumX_service"];
 		
 		NSArray			*children = [[xmlDoc rootElement] children];
-		NSCalendarDate	*startDate = nil, *endDate = nil;
+		NSDate			*startDate = nil, *endDate = nil;
 
 		if ([children count]) {
 			NSString		*dateStr;
+			ISO8601DateFormatter *formatter = [[[ISO8601DateFormatter alloc] init] autorelease];
 
 			dateStr = [[(NSXMLElement *)[children objectAtIndex:0] attributeForName:@"time"] objectValue];
-			startDate = (dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil);
+			startDate = (dateStr ? [formatter dateFromString:dateStr] : nil);
 			if (startDate)
 				[(NSMutableDictionary *)attributes setObject:startDate
 													  forKey:(NSString *)kMDItemContentCreationDate];
 
 			dateStr = [[(NSXMLElement *)[children lastObject] attributeForName:@"time"] objectValue];
-			endDate = (dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil);
+			endDate = (dateStr ? [formatter dateFromString:dateStr] : nil);
 			if (endDate)
 				[(NSMutableDictionary *)attributes setObject:[NSNumber numberWithDouble:[endDate timeIntervalSinceDate:startDate]]
 													  forKey:(NSString *)kMDItemDurationSeconds];
--- a/Other/Adium Spotlight Importer/GetMetadataForHTMLLog.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Other/Adium Spotlight Importer/GetMetadataForHTMLLog.m	Wed Oct 30 23:29:05 2013 -0400
@@ -19,36 +19,26 @@
 
 #include <sys/stat.h>
 
-#import "scandate.h"
+#import <AIUtilities/ISO8601DateFormatter.h>
 
 static char *gaim_markup_strip_html(const char *str);
 
-//Given an Adium log file name, return an NSCalendarDate for its creation date
+//Given an Adium log file name, return an NSDate for its creation date
 static NSDate *dateFromHTMLLog(NSString *pathToFile)
 {
-	NSDate *date = nil;
-	unsigned long   year = 0;
-	unsigned long   month = 0;
-	unsigned long   day = 0;
-	unsigned long   hour = 0;
-	unsigned long   minute = 0;
-	unsigned long   second = 0;
-	long   timeZoneOffset = +0;
-
-	if (scandate([pathToFile UTF8String], &year, &month, &day, /*outHasTime*/ NULL, &hour, &minute, &second, &timeZoneOffset)) {
-		if (year && month && day) {
-			NSCalendarDate *calendarDate = [NSCalendarDate dateWithYear:year
-																  month:month
-																	day:day
-																   hour:hour
-																 minute:minute
-																 second:second
-															   timeZone:[NSTimeZone timeZoneForSecondsFromGMT:(NSInteger)timeZoneOffset]];
-			date = [NSDate dateWithTimeIntervalSince1970:[calendarDate timeIntervalSince1970]];
+	ISO8601DateFormatter *formatter = [[[ISO8601DateFormatter alloc] init] autorelease];
+	formatter.timeSeparator = '.';
+	NSRange openParenRange, closeParenRange;
+	
+	if ([pathToFile hasSuffix:@".chatlog"] && (openParenRange = [pathToFile rangeOfString:@"(" options:NSBackwardsSearch]).location != NSNotFound) {
+		openParenRange = NSMakeRange(openParenRange.location, [pathToFile length] - openParenRange.location);
+		if ((closeParenRange = [pathToFile rangeOfString:@")" options:0 range:openParenRange]).location != NSNotFound) {
+			//Add and subtract one to remove the parenthesis
+			NSString *dateString = [pathToFile substringWithRange:NSMakeRange(openParenRange.location + 1, (closeParenRange.location - openParenRange.location))];
+			return [formatter dateFromString:dateString];
 		}
 	}
-	
-	return date;
+	return nil;
 }
 
 NSString *CopyTextContentForHTMLLogData(NSData *logData) {
--- a/Plugins/Error Message Handler/ErrorMessageHandlerPlugin.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Plugins/Error Message Handler/ErrorMessageHandlerPlugin.m	Wed Oct 30 23:29:05 2013 -0400
@@ -111,7 +111,7 @@
     __block NSString    *dateString;
 	
 	[NSDateFormatter withLocalizedDateFormatterShowingSeconds:NO showingAMorPM:YES perform:^(NSDateFormatter *dateFormatter){
-		dateString =  [[dateFormatter stringFromDate:[NSCalendarDate calendarDate]] retain];
+		dateString =  [[dateFormatter stringFromDate:[NSDate date]] retain];
 	}];
 	[dateString autorelease];
 	
--- a/Plugins/Message Alias Support/AIMessageAliasPlugin.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Plugins/Message Alias Support/AIMessageAliasPlugin.m	Wed Oct 30 23:29:05 2013 -0400
@@ -171,7 +171,7 @@
 
 	//Current Date
 	if ([self string:str containsValidKeyword:@"%d"]) {
-		NSCalendarDate	*currentDate = [NSCalendarDate calendarDate];
+		NSDate	*currentDate = [NSDate date];
 		__block NSString *calendarFormat;
 		[NSDateFormatter withLocalizedShortDateFormatterPerform:^(NSDateFormatter *dateFormatter){
 			calendarFormat = [[dateFormatter dateFormat] retain];
@@ -181,14 +181,14 @@
 		if (!newAttributedString) newAttributedString = [[attributedString mutableCopy] autorelease];
 		
 		[newAttributedString replaceOccurrencesOfString:@"%d"
-											 withString:[currentDate descriptionWithCalendarFormat:calendarFormat]
+											 withString:[currentDate descriptionWithCalendarFormat:calendarFormat timeZone:nil locale:nil]
 												options:NSLiteralSearch
 												  range:NSMakeRange(0, [newAttributedString length])];
 	}
 	
 	//Current Time
 	if ([self string:str containsValidKeyword:@"%t"]) {
-		NSCalendarDate 	*currentDate = [NSCalendarDate calendarDate];
+		NSDate 	*currentDate = [NSDate date];
 		
 		if (!newAttributedString) newAttributedString = [[attributedString mutableCopy] autorelease];
 
--- a/Plugins/Purple Service/CBPurpleOscarAccount.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Plugins/Purple Service/CBPurpleOscarAccount.m	Wed Oct 30 23:29:05 2013 -0400
@@ -30,7 +30,6 @@
 #import <Adium/AIStatus.h>
 #import <AIUtilities/AIAttributedStringAdditions.h>
 #import <AIUtilities/AIDateFormatterAdditions.h>
-#import <AIUtilities/NSCalendarDate+ISO8601Parsing.h>
 #import <AIUtilities/AIImageAdditions.h>
 #import <AIUtilities/AIObjectAdditions.h>
 #import <AIUtilities/AIStringAdditions.h>
--- a/Source/AICalendarDate.h	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-
-typedef enum {
-	AIDayGranularity = 0,
-	AISecondGranularity
-} AICalendarDateGranularity;
-
-@interface AICalendarDate : NSCalendarDate {
-	AICalendarDateGranularity granularity;
-}
-
-- (void)setGranularity:(AICalendarDateGranularity)inGranularity;
-- (AICalendarDateGranularity)granularity;
-
-@end
--- a/Source/AICalendarDate.m	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import "AICalendarDate.h"
-
-
-@implementation AICalendarDate
-/*!
- * @brief Initialize with coder
- */
-- (id)initWithCoder:(NSCoder *)decoder
-{
-	if ((self = [super initWithCoder:decoder])) {
-		if ([decoder allowsKeyedCoding]) {
-			granularity = [[decoder decodeObjectForKey:@"Granularity"] intValue];
-		} else {
-			granularity = [[decoder decodeObject] intValue];			
-		}
-	}
-	
-	return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)encoder
-{
-	[super encodeWithCoder:encoder];
-
-	if ([encoder allowsKeyedCoding]) {
-        [encoder encodeObject:[NSNumber numberWithInteger:granularity] forKey:@"Granularity"];
-		
-    } else {
-        [encoder encodeObject:[NSNumber numberWithInteger:granularity]];
-    }
-}
-
-- (id)copyWithZone:(NSZone *)inZone
-{
-	AICalendarDate *newDate = [super copyWithZone:inZone];
-	newDate->granularity = granularity;
-
-	return newDate;
-}
-
-- (void)setGranularity:(AICalendarDateGranularity)inGranularity
-{
-	granularity = inGranularity;
-}
-- (AICalendarDateGranularity)granularity
-{
-	return granularity;
-}
-@end
--- a/Source/AIChatLog.h	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AIChatLog.h	Wed Oct 30 23:29:05 2013 -0400
@@ -16,14 +16,19 @@
 
 #define ChatLog_WillDelete			@"ChatLog_WillDelete"
 
+@class ISO8601DateFormatter;
+
+NSDate *dateFromFileName(NSString *fileName);
+
 @interface AIChatLog : NSObject <NSXMLParserDelegate> {
     NSString	    *relativePath;
     NSString	    *from;
     NSString	    *to;
 	NSString		*serviceClass;
-    NSCalendarDate	*date;
+    NSDate			*date;
 	CGFloat			rankingPercentage;
 	CGFloat			rankingValue;
+	ISO8601DateFormatter *formatter;
 }
 
 - (id)initWithPath:(NSString *)inPath from:(NSString *)inFrom to:(NSString *)inTo serviceClass:(NSString *)inServiceClass;
@@ -34,14 +39,13 @@
 - (NSString *)from;
 - (NSString *)to;
 - (NSString *)serviceClass;
-- (NSCalendarDate *)date;
+- (NSDate *)date;
 - (CGFloat)rankingPercentage;
 - (void)setRankingPercentage:(CGFloat)inRankingPercentage;
 - (CGFloat)rankingValueOnArbitraryScale;
 - (void)setRankingValueOnArbitraryScale:(CGFloat)inRankingValue;
 
 //Comparisons
-- (BOOL)isFromSameDayAsDate:(NSCalendarDate *)inDate;
 - (NSComparisonResult)compareTo:(AIChatLog *)inLog;
 - (NSComparisonResult)compareToReverse:(AIChatLog *)inLog;
 - (NSComparisonResult)compareFrom:(AIChatLog *)inLog;
--- a/Source/AIChatLog.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AIChatLog.m	Wed Oct 30 23:29:05 2013 -0400
@@ -18,15 +18,11 @@
 #import "AILoginController.h"
 #import "AILogViewerWindowController.h"
 #import "AILoggerPlugin.h"
-#import "AICalendarDate.h"
 
-#import <AIUtilities/NSCalendarDate+ISO8601Parsing.h>
-#import "scandate.h"
+#import <AIUtilities/ISO8601DateFormatter.h>
 
 @implementation AIChatLog
 
-static NSCalendarDate *dateFromFileName(NSString *fileName);
-
 - (id)initWithPath:(NSString *)inPath from:(NSString *)inFrom to:(NSString *)inTo serviceClass:(NSString *)inServiceClass
 {
     if ((self = [super init])) {
@@ -35,6 +31,8 @@
 		to = [inTo retain];
 		serviceClass = [inServiceClass retain];
 		rankingPercentage = 0;
+		
+		formatter = [[ISO8601DateFormatter alloc] init];
 	}
 
     return self;
@@ -77,6 +75,7 @@
     [to release];
 	[serviceClass release];
     [date release];
+	[formatter release];
     
     [super dealloc];
 }
@@ -93,7 +92,7 @@
 - (NSString *)serviceClass{
 	return serviceClass;
 }
-- (NSCalendarDate *)date{
+- (NSDate *)date{
 	//Determine the date of this log lazily
 	if (!date) {
 		date = [dateFromFileName([relativePath lastPathComponent]) retain];
@@ -116,7 +115,7 @@
 	//Stop at the first element with a date.
 	NSString *dateString = nil;
 	if ((dateString = [attributeDict objectForKey:@"time"])) {
-		date = [[NSCalendarDate calendarDateWithString:dateString strictly:YES] retain];
+		date = [[formatter dateFromString:dateString] retain];
 		if (date)
 			[parser abortParsing];
 	}
@@ -140,11 +139,6 @@
 	return rankingValue;
 }
 
-- (BOOL)isFromSameDayAsDate:(NSCalendarDate *)inDate
-{
-	return [[self date] dayOfCommonEra] == [inDate dayOfCommonEra];
-}
-
 #pragma mark Sort Selectors
 
 //Sort by To, then Date
@@ -307,35 +301,21 @@
 
 #pragma mark Date utilities
 
-//Given an Adium log file name, return an NSCalendarDate with year, month, and day specified
-static NSCalendarDate *dateFromFileName(NSString *fileName)
+//Given an Adium log file name, return an NSDate with year, month, and day specified
+NSDate *dateFromFileName(NSString *fileName)
 {
-	unsigned long   year = 0;
-	unsigned long   month = 0;
-	unsigned long   day = 0;
-	unsigned long   hour = 0;
-	unsigned long   minute = 0;
-	unsigned long   second = 0;
-	  long   tzone = NSNotFound;
-	BOOL			hasTime = NO;
-	  
-	if (scandate([fileName UTF8String], &year, &month, &day, &hasTime, &hour, &minute, &second, &tzone)) {
-		if (year && month && day) {
-			AICalendarDate *calendarDate;
-			
-			calendarDate = [AICalendarDate dateWithYear:year
-												  month:month
-													day:day
-												   hour:hour
-												 minute:minute
-												 second:second
-											   timeZone:((tzone == NSNotFound) ? nil : [NSTimeZone timeZoneForSecondsFromGMT:(tzone * 60)])];
-			[calendarDate setGranularity:(hasTime ? AISecondGranularity : AIDayGranularity)];
-
-			return calendarDate;
+	ISO8601DateFormatter *formatter = [[[ISO8601DateFormatter alloc] init] autorelease];
+	formatter.timeSeparator = '.';
+	NSRange openParenRange, closeParenRange;
+	
+	if ([fileName hasSuffix:@".chatlog"] && (openParenRange = [fileName rangeOfString:@"(" options:NSBackwardsSearch]).location != NSNotFound) {
+		openParenRange = NSMakeRange(openParenRange.location, [fileName length] - openParenRange.location);
+		if ((closeParenRange = [fileName rangeOfString:@")" options:0 range:openParenRange]).location != NSNotFound) {
+			//Add and subtract one to remove the parenthesis
+			NSString *dateString = [fileName substringWithRange:NSMakeRange(openParenRange.location + 1, (closeParenRange.location - openParenRange.location))];
+			return [formatter dateFromString:dateString];
 		}
 	}
-	
 	return nil;
 }
 
--- a/Source/AILogDateFormatter.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AILogDateFormatter.m	Wed Oct 30 23:29:05 2013 -0400
@@ -15,7 +15,7 @@
  */
 
 #import "AILogDateFormatter.h"
-#import "AICalendarDate.h"
+#import <AIUtilities/AIDateAdditions.h>
 
 @implementation AILogDateFormatter
 
@@ -23,30 +23,34 @@
 {
 	NSString *returnValue = nil;
 
-	if ([self respondsToSelector:@selector(timeStyle)] && [date isKindOfClass:[AICalendarDate class]]) {
-		NSInteger today = [[NSCalendarDate calendarDate] dayOfCommonEra];
-		NSInteger dateDay = [(AICalendarDate *)date dayOfCommonEra];
+	if ([self respondsToSelector:@selector(timeStyle)] && [date isKindOfClass:[NSDate class]]) {
 		NSDateFormatterStyle timeStyle = [self timeStyle];
-
-		if ((dateDay == today) || (dateDay == (today - 1))) {
-			NSString			*dayString = (dateDay == today) ? AILocalizedString(@"Today", "Day designation for the current day") : AILocalizedString(@"Yesterday", "Day designation for the previous day");
-			if ((timeStyle != NSDateFormatterNoStyle) &&
-				([(AICalendarDate *)date granularity] == AISecondGranularity)) {
+		
+		NSDate *dateToday = [NSDate date];
+		NSCalendar *calendar = [NSCalendar currentCalendar];
+		NSDateComponents *comps = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
+											  fromDate:dateToday];
+		comps.day--;
+		BOOL today = [NSDate isDate:dateToday sameDayAsDate:date];
+		BOOL yesterday = [NSDate isDate:[calendar dateFromComponents:comps] sameDayAsDate:date];
+		
+		if (today || yesterday) {
+			NSString			*dayString = today ? AILocalizedString(@"Today", "Day designation for the current day") : AILocalizedString(@"Yesterday", "Day designation for the previous day");
+			if (timeStyle != NSDateFormatterNoStyle) {
 				//Supposed to show time, and the date has sufficient granularity to show it
 				NSDateFormatterStyle dateStyle = [self dateStyle];
 				NSMutableString *mutableString = [dayString mutableCopy];
-
+				
 				[self setDateStyle:NSDateFormatterNoStyle];
 				[mutableString appendString:@" "];
 				[mutableString appendString:[super stringForObjectValue:date]];
 				[self setDateStyle:dateStyle];
-	
-				returnValue = [mutableString autorelease];
+				
+				returnValue = mutableString;
 			}
-
+			
 		} else {
-			if ((timeStyle != NSDateFormatterNoStyle) &&
-				([(AICalendarDate *)date granularity] == AIDayGranularity)) {
+			if (timeStyle != NSDateFormatterNoStyle) {
 				//Currently supposed to show time, but the date does not have that level of granularity
 				
 				[self setTimeStyle:NSDateFormatterNoStyle];
@@ -55,10 +59,10 @@
 			}
 		}
 	}
-
+	
 	if (![returnValue length]) returnValue = [super stringForObjectValue:date];
 	if (![returnValue length]) returnValue = [date description];
-
+	
 	return returnValue;
 }
 
--- a/Source/AILogViewerWindowController.h	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AILogViewerWindowController.h	Wed Oct 30 23:29:05 2013 -0400
@@ -92,9 +92,7 @@
 	NSMutableSet		*contactIDsToFilter;
 
 	AIDateType			filterDateType;
-	NSCalendarDate		*filterDate;
-	NSInteger			firstDayOfWeek;
-	BOOL				iCalFirstDayOfWeekDetermined;
+	NSDate				*filterDate;
 
 	NSMutableDictionary	*logToGroupDict;
 	NSMutableDictionary	*logFromGroupDict;
--- a/Source/AILogViewerWindowController.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AILogViewerWindowController.m	Wed Oct 30 23:29:05 2013 -0400
@@ -42,6 +42,7 @@
 #import <AIUtilities/AIArrayAdditions.h>
 #import <AIUtilities/AIAttributedStringAdditions.h>
 #import <AIUtilities/AIDateFormatterAdditions.h>
+#import <AIUtilities/AIDateAdditions.h>
 #import <AIUtilities/AIFileManagerAdditions.h>
 #import <AIUtilities/AIImageAdditions.h>
 #import <AIUtilities/AIOutlineViewAdditions.h>
@@ -1478,7 +1479,7 @@
 			matchesDateFilter = ([[inChatLog date] timeIntervalSinceDate:filterDate] < 0);
 			break;
 		case AIDateTypeExactly:
-			matchesDateFilter = [inChatLog isFromSameDayAsDate:filterDate];
+			matchesDateFilter = [NSDate isDate:[inChatLog date] sameDayAsDate:filterDate];
 			break;
 		default:
 			matchesDateFilter = YES;
@@ -1768,7 +1769,7 @@
 {
     UInt32		lastUpdate = TickCount();
     
-    NSCalendarDate	*searchStringDate = nil;
+    NSDate	*searchStringDate = nil;
 	
 	if ((mode == LOG_SEARCH_DATE) && (searchString != nil)) {
 		searchStringDate = [[NSDate dateWithNaturalLanguageString:searchString]  dateWithCalendarFormat:nil timeZone:nil];
@@ -1806,7 +1807,7 @@
 						 */
 						if ((mode != LOG_SEARCH_DATE) ||
 						   (!searchString) ||
-						   (searchStringDate && [theLog isFromSameDayAsDate:searchStringDate])) {
+						   (searchStringDate && [NSDate isDate:[theLog date] sameDayAsDate:searchStringDate])) {
 
 							if ([self chatLogMatchesDateFilter:theLog]) {
 								//Add the log
@@ -2429,25 +2430,11 @@
     return [menuItem autorelease];
 }
 
-- (NSInteger)daysSinceStartOfWeekGivenToday:(NSCalendarDate *)today
+- (NSInteger)daysSinceStartOfWeekGivenToday:(NSDate *)today
 {
-	NSInteger todayDayOfWeek = [today dayOfWeek];
-
-	//Try to look at the iCal preferences if possible
-	if (!iCalFirstDayOfWeekDetermined) {
-		CFPropertyListRef iCalFirstDayOfWeek = CFPreferencesCopyAppValue(CFSTR("first day of week"),CFSTR("com.apple.iCal"));
-		if (iCalFirstDayOfWeek) {
-			//This should return a CFNumberRef... we're using another app's prefs, so make sure.
-			if (CFGetTypeID(iCalFirstDayOfWeek) == CFNumberGetTypeID()) {
-				firstDayOfWeek = [(NSNumber *)iCalFirstDayOfWeek integerValue];
-			}
-
-			CFRelease(iCalFirstDayOfWeek);
-		}
-
-		//Don't check again
-		iCalFirstDayOfWeekDetermined = YES;
-	}
+	NSInteger todayDayOfWeek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit
+																fromDate:today] weekday];
+	NSInteger firstDayOfWeek = [[NSCalendar currentCalendar] firstWeekday];
 
 	return ((todayDayOfWeek >= firstDayOfWeek) ? (todayDayOfWeek - firstDayOfWeek) : ((todayDayOfWeek + 7) - firstDayOfWeek));
 }
@@ -2959,9 +2946,6 @@
 
 - (void)configureDateFilter
 {
-	firstDayOfWeek = 0; /* Sunday */
-	iCalFirstDayOfWeekDetermined = NO;
-	
 	[popUp_dateFilter setMenu:[self dateTypeMenu]];
 	NSInteger idx = [popUp_dateFilter indexOfItemWithTag:AIDateTypeAnyDate];
 	if(idx != NSNotFound)
@@ -3025,7 +3009,9 @@
 {
 	BOOL			showDatePicker = NO;
 	
-	NSCalendarDate	*today = [NSCalendarDate date];
+	NSDate	*today = [NSDate date];
+	NSCalendar *calendar = [NSCalendar currentCalendar];
+	NSDateComponents *comps = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:today];
 	
 	[filterDate release]; filterDate = nil;
 	
@@ -3041,52 +3027,48 @@
 			
 		case AIDateTypeSinceYesterday:
 			filterDateType = AIDateTypeAfter;
-			filterDate = [[today dateByAddingYears:0
-											months:0
-											  days:-1
-											 hours:-[today hourOfDay]
-										   minutes:-[today minuteOfHour]
-										   seconds:-([today secondOfMinute] + 1)] retain];
+			comps.day--;
+			comps.hour -= comps.hour;
+			comps.minute -= comps.minute;
+			comps.second -= comps.second + 1;
+			filterDate = [[calendar dateFromComponents:comps] retain];
 			break;
 			
 		case AIDateTypeThisWeek:
 			filterDateType = AIDateTypeAfter;
-			filterDate = [[today dateByAddingYears:0
-											months:0
-											  days:-[self daysSinceStartOfWeekGivenToday:today]
-											 hours:-[today hourOfDay]
-										   minutes:-[today minuteOfHour]
-										   seconds:-([today secondOfMinute] + 1)] retain];
+			comps.day -= [self daysSinceStartOfWeekGivenToday:today];
+			comps.hour -= comps.hour;
+			comps.minute -= comps.minute;
+			comps.second -= comps.second + 1;
+			filterDate = [[calendar dateFromComponents:comps] retain];
 			break;
 			
 		case AIDateTypeWithinLastTwoWeeks:
 			filterDateType = AIDateTypeAfter;
-			filterDate = [[today dateByAddingYears:0
-											months:0
-											  days:-14
-											 hours:-[today hourOfDay]
-										   minutes:-[today minuteOfHour]
-										   seconds:-([today secondOfMinute] + 1)] retain];
+			comps.day -= 14;
+			comps.hour -= comps.hour;
+			comps.minute -= comps.minute;
+			comps.second -= comps.second + 1;
+			filterDate = [[calendar dateFromComponents:comps] retain];
 			break;
 			
 		case AIDateTypeThisMonth:
 			filterDateType = AIDateTypeAfter;
-			filterDate = [[[NSCalendarDate date] dateByAddingYears:0
-															months:0
-															  days:-[today dayOfMonth]
-															 hours:0
-														   minutes:0
-														   seconds:-1] retain];
+			comps.day -= comps.day;
+			comps.hour -= comps.hour;
+			comps.minute -= comps.minute;
+			comps.second -= comps.second + 1;
+			filterDate = [[calendar dateFromComponents:comps] retain];
 			break;
 			
 		case AIDateTypeWithinLastTwoMonths:
 			filterDateType = AIDateTypeAfter;
-			filterDate = [[[NSCalendarDate date] dateByAddingYears:0
-															months:-1
-															  days:-[today dayOfMonth]
-															 hours:0
-														   minutes:0
-														   seconds:-1] retain];
+			comps.month--;
+			comps.day -= comps.day;
+			comps.hour = 0;
+			comps.minute = 0;
+			comps.second--;
+			filterDate = [[calendar dateFromComponents:comps] retain];
 			break;
 			
 		default:
--- a/Source/AILoggerPlugin.h	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AILoggerPlugin.h	Wed Oct 30 23:29:05 2013 -0400
@@ -28,7 +28,7 @@
 
 #define XML_LOGGING_NAMESPACE         @"http://purl.org/net/ulf/ns/0.4-02"
 
-@class AIAccount, AIHTMLDecoder, AIChat;
+@class AIAccount, AIHTMLDecoder, AIChat, ISO8601DateFormatter;
 
 @interface AILoggerPlugin : AIPlugin {
 	
@@ -45,6 +45,8 @@
 	NSDictionary        *statusTranslation;
 	BOOL                 logHTML;
 	
+	ISO8601DateFormatter *formatter;
+	
 	// Log Indexing
 	NSMutableSet        *dirtyLogSet;
 	BOOL                 indexingAllowed;
--- a/Source/AILoggerPlugin.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AILoggerPlugin.m	Wed Oct 30 23:29:05 2013 -0400
@@ -46,8 +46,7 @@
 #import <AIUtilities/AIToolbarUtilities.h>
 #import <AIUtilities/AIDateFormatterAdditions.h>
 #import <AIUtilities/AIImageAdditions.h>
-#import <AIUtilities/NSCalendarDate+ISO8601Unparsing.h>
-#import <AIUtilities/NSCalendarDate+ISO8601Parsing.h>
+#import <AIUtilities/ISO8601DateFormatter.h>
 
 #import <libkern/OSAtomic.h>
 
@@ -157,7 +156,6 @@
 #pragma mark Private Function Prototypes
 void runWithAutoreleasePool(dispatch_block_t block);
 static inline dispatch_block_t blockWithAutoreleasePool(dispatch_block_t block);
-NSCalendarDate* getDateFromPath(NSString *path);
 NSComparisonResult sortPaths(NSString *path1, NSString *path2, void *context);
 
 #pragma mark -
@@ -224,6 +222,8 @@
 	jobSemaphore = dispatch_semaphore_create(3 * cpuCount);
     logLoadingPrefetchSemaphore = dispatch_semaphore_create(3 * cpuCount + 1); //prefetch one log
 	
+	formatter = [[ISO8601DateFormatter alloc] init];
+	formatter.includeTime = YES;
 	
 	self.xhtmlDecoder = [[[AIHTMLDecoder alloc] initWithHeaders:NO
 													   fontTags:YES
@@ -338,6 +338,8 @@
 	dispatch_release(jobSemaphore); jobSemaphore = nil;
 	dispatch_release(loggerPluginGroup); loggerPluginGroup = nil;
 	
+	[formatter release]; formatter = nil;
+	
 	[super dealloc];
 }
 #pragma mark AILoggerPlugin Plubic Methods
@@ -378,7 +380,7 @@
 	NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self pathForLogsLikeChat:chat] error:NULL];
 	NSMutableArray *dates = [NSMutableArray arrayWithCapacity:files.count];
 	for (NSString *path in files) {
-		id date = getDateFromPath(path);
+		id date = dateFromFileName(path);
 		[dates addObject:date ?: [NSNull null]];
 	}
 	
@@ -554,22 +556,6 @@
 	} copy] autorelease];
 }
 
-NSCalendarDate* getDateFromPath(NSString *path)
-{
-	NSRange openParenRange, closeParenRange;
-	
-	if ([path hasSuffix:@".chatlog"] && (openParenRange = [path rangeOfString:@"(" options:NSBackwardsSearch]).location != NSNotFound) {
-		openParenRange = NSMakeRange(openParenRange.location, [path length] - openParenRange.location);
-		if ((closeParenRange = [path rangeOfString:@")" options:0 range:openParenRange]).location != NSNotFound) {
-			//Add and subtract one to remove the parenthesis
-			NSString *dateString = [path substringWithRange:NSMakeRange(openParenRange.location + 1, (closeParenRange.location - openParenRange.location))];
-			NSCalendarDate *date = [NSCalendarDate calendarDateWithString:dateString timeSeparator:'.'];
-			return date;
-		}
-	}
-	return nil;
-}
-
 NSComparisonResult sortPaths(NSString *path1, NSString *path2, void *context)
 {
 	NSDictionary *cache = (NSDictionary *)context;
@@ -1040,7 +1026,7 @@
 		dispatch_group_async(logAppendingGroup, dispatch_get_main_queue(), blockWithAutoreleasePool(^{
 			BOOL			dirty = NO;
 			NSString		*contentType = [content type];
-			NSString		*date = [[[content date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString];
+			NSString		*date = [formatter stringFromDate:[[content date] dateWithCalendarFormat:nil timeZone:nil]];
 			
 			if ([contentType isEqualToString:CONTENT_MESSAGE_TYPE] ||
 				[contentType isEqualToString:CONTENT_CONTEXT_TYPE]) {
@@ -1177,7 +1163,7 @@
 		AIXMLElement *eventElement = [[[AIXMLElement alloc] initWithName:@"event"] autorelease];
 		
 		[eventElement setAttributeNames:[NSArray arrayWithObjects:@"type", @"sender", @"time", nil]
-								 values:[NSArray arrayWithObjects:@"windowOpened", chat.account.UID, [[[NSDate date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString], nil]];
+								 values:[NSArray arrayWithObjects:@"windowOpened", chat.account.UID, [formatter stringFromDate:[[NSDate date] dateWithCalendarFormat:nil timeZone:nil]], nil]];
 		
 		[appender appendElement:eventElement];
 		
@@ -1199,7 +1185,7 @@
 		AIXMLElement *eventElement = [[[AIXMLElement alloc] initWithName:@"event"] autorelease];
 		
 		[eventElement setAttributeNames:[NSArray arrayWithObjects:@"type", @"sender", @"time", nil]
-								 values:[NSArray arrayWithObjects:@"windowClosed", chat.account.UID, [[[NSDate date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString], nil]];
+								 values:[NSArray arrayWithObjects:@"windowClosed", chat.account.UID, [formatter stringFromDate:[[NSDate date] dateWithCalendarFormat:nil timeZone:nil]], nil]];
 		
 		
 		[appender appendElement:eventElement];
@@ -1259,7 +1245,7 @@
 		AIXMLElement *eventElement = [[[AIXMLElement alloc] initWithName:@"event"] autorelease];
 		
 		[eventElement setAttributeNames:[NSArray arrayWithObjects:@"type", @"sender", @"time", nil]
-								 values:[NSArray arrayWithObjects:@"windowOpened", chat.account.UID, [[[NSDate date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString], nil]];
+								 values:[NSArray arrayWithObjects:@"windowOpened", chat.account.UID, [formatter stringFromDate:[[NSDate date] dateWithCalendarFormat:nil timeZone:nil]], nil]];
 		
 		[appender appendElement:eventElement];
 		
--- a/Source/AIXMLChatlogConverter.h	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AIXMLChatlogConverter.h	Wed Oct 30 23:29:05 2013 -0400
@@ -25,12 +25,13 @@
 	AIScreenName = 4
 } AINameFormat;
 
-@class AIHTMLDecoder;
+@class AIHTMLDecoder, ISO8601DateFormatter;
 
 @interface AIXMLChatlogConverter : NSObject {
 	NSDictionary	*statusLookup;
     NSAttributedString *newlineAttributedString;
 	AIHTMLDecoder	*htmlDecoder;
+	ISO8601DateFormatter *formatter;
 }
 
 + (NSAttributedString *)readFile:(NSString *)filePath withOptions:(NSDictionary *)options;
--- a/Source/AIXMLChatlogConverter.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/AIXMLChatlogConverter.m	Wed Oct 30 23:29:05 2013 -0400
@@ -23,7 +23,7 @@
 #import <Adium/AIContactControllerProtocol.h>
 #import <Adium/AIContentControllerProtocol.h>
 #import <Adium/AIStatusControllerProtocol.h>
-#import <AIUtilities/NSCalendarDate+ISO8601Parsing.h>
+#import <AIUtilities/ISO8601DateFormatter.h>
 #import <AIUtilities/AIDateFormatterAdditions.h>
 #import <AIUtilities/AIStringAdditions.h>
 
@@ -140,7 +140,9 @@
 			[adium.statusController localizedDescriptionForCoreStatusName:STATUS_NAME_NOT_AT_DESK], @"notAtMyDesk",
 			[adium.statusController localizedDescriptionForCoreStatusName:STATUS_NAME_NOT_IN_OFFICE], @"notInTheOffice",
 			[adium.statusController localizedDescriptionForCoreStatusName:STATUS_NAME_STEPPED_OUT], @"steppedOut",
-			nil];			
+			nil];
+		
+		formatter = [[ISO8601DateFormatter alloc] init];
 	}
 
 	return self;
@@ -150,6 +152,7 @@
 {
 	[statusLookup release];
 	[htmlDecoder release];
+	[formatter release];
 	[super dealloc];
 }
 
@@ -210,7 +213,7 @@
         if ([type isEqualToString:@"message"]) {
             NSString *senderAlias = [[attributes objectForKey:@"alias"] stringValue];
             NSString *dateStr = [[attributes objectForKey:@"time"] stringValue];
-            NSDate *date = dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil;
+            NSDate *date = dateStr ? [formatter dateFromString:dateStr] : nil;
             NSString *sender = [[attributes objectForKey:@"sender"] stringValue];
             NSString *shownSender = (senderAlias ? senderAlias : sender);
             BOOL autoResponse = [[[attributes objectForKey:@"auto"] stringValue] isEqualToString:@"true"];
@@ -288,7 +291,7 @@
             [output appendAttributedString:newlineAttributedString];
         } else if ([type isEqualToString:@"status"]) {
             NSString *dateStr = [[attributes objectForKey:@"time"] stringValue];
-            NSDate *date = dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil;
+            NSDate *date = dateStr ? [formatter dateFromString:dateStr] : nil;
             NSString *status = [[attributes objectForKey:@"type"] stringValue];
             
             NSMutableString *messageXML = [NSMutableString string];
--- a/Source/BGICLogImportController.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/BGICLogImportController.m	Wed Oct 30 23:29:05 2013 -0400
@@ -21,7 +21,7 @@
 #import <Adium/AIXMLElement.h>
 #import <Adium/AIHTMLDecoder.h>
 #import <Adium/AILoginControllerProtocol.h>
-#import <AIUtilities/NSCalendarDate+ISO8601Unparsing.h>
+#import <AIUtilities/ISO8601DateFormatter.h>
 #import <AIUtilities/AIFileManagerAdditions.h>
 #import <AIUtilities/AIStringAdditions.h>
 
@@ -116,13 +116,15 @@
 	AIXMLAppender *appender = [AIXMLAppender documentWithPath:documentPath rootElement:rootElement];
 	NSString	  *imagesPath = [appender.path stringByDeletingLastPathComponent];
 	
+	ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init];
+	formatter.includeTime = YES;
 	// sequentially add the messages from the iChat transcript sans attributed text features
 	for(NSInteger i = 0; i < [[rawChat objectAtIndex:2] count]; i++)
 	{
 		NSMutableArray *attributeKeys = [NSMutableArray arrayWithObjects:@"sender", @"time", nil];
 		NSMutableArray *attributeValues = [NSMutableArray arrayWithObjects:
 			([[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] sender] senderID] != nil ? [[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] sender] senderID] : @""), 
-			[[[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString], 
+			[formatter stringFromDate:[[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] date] dateWithCalendarFormat:nil timeZone:nil]],
 			nil];
 		
 		NSMutableString *chatContents = [[[xhtmlDecoder encodeHTML:[[[rawChat objectAtIndex:2] objectAtIndex:i] text] imagesPath:imagesPath] mutableCopy] autorelease];
--- a/Source/DCMessageContextDisplayPlugin.h	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/DCMessageContextDisplayPlugin.h	Wed Oct 30 23:29:05 2013 -0400
@@ -25,13 +25,14 @@
 
 #define CONTEXT_DISPLAY_DEFAULTS	@"MessageContextDisplayDefaults"
 
-@class SMSQLiteLoggerPlugin;
+@class SMSQLiteLoggerPlugin, ISO8601DateFormatter;
 
 @interface DCMessageContextDisplayPlugin : AIPlugin {	
 	BOOL							isObserving;
 	BOOL							shouldDisplay;
 	BOOL							dimRecentContext;
 	NSInteger						linesToDisplay;
+	ISO8601DateFormatter			*formatter;
 }
 
 + (DCMessageContextDisplayPlugin *)sharedInstance;
--- a/Source/DCMessageContextDisplayPlugin.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/DCMessageContextDisplayPlugin.m	Wed Oct 30 23:29:05 2013 -0400
@@ -35,7 +35,7 @@
 #import <Adium/AIXMLElement.h>
 #import <AIUtilities/AIStringAdditions.h>
 #import "unistd.h"
-#import <AIUtilities/NSCalendarDate+ISO8601Parsing.h>
+#import <AIUtilities/ISO8601DateFormatter.h>
 #import <Adium/AIContactControllerProtocol.h>
 #import <Adium/AIHTMLDecoder.h>
 
@@ -81,6 +81,7 @@
 	[adium.preferenceController registerPreferenceObserver:self forGroup:PREF_GROUP_LOGGING];
 	
 	sharedInstance = self;
+	formatter = [[ISO8601DateFormatter alloc] init];
 }
 
 /**
@@ -88,6 +89,7 @@
  */
 - (void)uninstallPlugin
 {
+	[formatter release];
 	[adium.preferenceController unregisterPreferenceObserver:self];
 	[[NSNotificationCenter defaultCenter] removeObserver:self];
 }
@@ -386,7 +388,7 @@
 			NSString		*timeString = [attributes objectForKey:@"time"];
 			//Create the context object
 			if (timeString) {
-				NSCalendarDate *timeVal = [NSCalendarDate calendarDateWithString:timeString];
+				NSDate *timeVal = [formatter dateFromString:timeString];
 
 				NSString		*autoreplyAttribute = [attributes objectForKey:@"auto"];
 				NSString		*sender = [NSString stringWithFormat:@"%@.%@", serviceName, [attributes objectForKey:@"sender"]];
@@ -430,7 +432,7 @@
 			NSString		*timeString = [attributes objectForKey:@"time"];
 			
 			if (timeString) {
-				NSCalendarDate *timeVal = [NSCalendarDate calendarDateWithString:timeString];
+				NSDate *timeVal = [formatter dateFromString:timeString];
                 
                 AIContentStatus *status = [[AIContentStatus alloc] initWithChat:chat source:nil destination:nil date:timeVal];
                 
--- a/Source/ESDebugController.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/ESDebugController.m	Wed Oct 30 23:29:05 2013 -0400
@@ -182,7 +182,7 @@
 {
 	if (!debugLogFile) {
 		NSFileManager *mgr = [NSFileManager defaultManager];
-		NSCalendarDate *date = [NSCalendarDate calendarDate];
+		NSDate *date = [NSDate date];
 		NSString *folder, *dateString, *filename, *pathname;
 		NSUInteger counter = 0;
 		int fd;
@@ -203,7 +203,7 @@
 			*the date is in YYYY-MM-DD format. duplicates are disambiguated with
 			*' 1', ' 2', ' 3', etc. appendages.
 			*/
-		filename = dateString = [date descriptionWithCalendarFormat:@"%Y-%m-%d"];
+		filename = dateString = [date descriptionWithCalendarFormat:@"%Y-%m-%d" timeZone:nil locale:nil];
 		while([mgr fileExistsAtPath:(pathname = [folder stringByAppendingPathComponent:[filename stringByAppendingPathExtension:@"log"]])]) {
 			filename = [dateString stringByAppendingFormat:@" %lu", ++counter];
 		}
--- a/Source/ESiTunesPlugin.m	Wed Oct 30 18:34:07 2013 +0100
+++ b/Source/ESiTunesPlugin.m	Wed Oct 30 23:29:05 2013 -0400
@@ -29,6 +29,7 @@
 #import <AIUtilities/AIMenuAdditions.h>
 #import <AIUtilities/AIWindowAdditions.h>
 #import <AIUtilities/AIStringAdditions.h>
+#import <AIUtilities/AIApplicationAdditions.h>
 #import <Adium/AIHTMLDecoder.h>
 #import <Adium/AIStatus.h>
 #import <WebKit/WebKit.h>
--- a/Source/scandate.h	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*Input: A string in UTF-8 encoding containing an ISO 8601 date within a parenthesis.
- *Output:
- *- Year, month, and date
- *- Whether time was found
- *- The hour, minute, and second of that time
- *- The time zone offset as a single number of minutes
- *- (Return value) Whether a date was found.
- */
-BOOL scandate(const char *sample,
-              unsigned long *outyear, unsigned long *outmonth,  unsigned long *outdate,
-              BOOL *outHasTime, unsigned long *outhour, unsigned long *outminute, unsigned long *outsecond,
-              long *outtimezone);
--- a/Source/scandate.m	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import "scandate.h"
-
-BOOL scandate(const char *sample,
-					 unsigned long *outyear, unsigned long *outmonth,  unsigned long *outdate,
-					 BOOL *outHasTime, unsigned long *outhour, unsigned long *outminute, unsigned long *outsecond,
-					 long *outtimezone)
-{
-	BOOL success = YES;
-	unsigned long component;
-
-	const char *lastOpenParenthesis = NULL;
-
-    //Read a '(', followed by a date.
-	//First, find the '('.
-	while (*sample != '\0') {
-		if (*sample == '(')
-			lastOpenParenthesis = sample;
-		++sample;
-    }
-
-	if (!lastOpenParenthesis) {
-		success = NO;
-		goto fail;
-	}
-	sample = lastOpenParenthesis;
-
-	//current character is a '(' now, so skip over it.
-    ++sample; //start with the next character
-	
-    /*get the year*/ {
-		while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-		if (!*sample) {
-			success = NO;
-			goto fail;
-		}
-		component = strtoul(sample, (char **)&sample, 10);
-		if (outyear) *outyear = component;
-    }
-    
-    /*get the month*/ {
-		while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-		if (!*sample) {
-			success = NO;
-			goto fail;
-		}
-		component = strtoul(sample, (char **)&sample, 10);
-		if (outmonth) *outmonth = component;
-    }
-    
-    /*get the date*/ {
-		while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-		if (!*sample) {
-			success = NO;
-			goto fail;
-		}
-		component = strtoul(sample, (char **)&sample, 10);
-		if (outdate) *outdate = component;
-    }
-
-    if (*sample == 'T') {
-		++sample; //start with the next character
-		if (outHasTime) *outHasTime = YES;
-		
-		/*get the hour*/ {
-			while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-			if (!*sample) {
-				success = NO;
-				goto fail;
-			}
-			component = strtoul(sample, (char **)&sample, 10);
-			if (outhour) *outhour = component;
-		}
-
-		/*get the minute*/ {
-			while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-			if (!*sample) {
-				success = NO;
-				goto fail;
-			}
-			component = strtoul(sample, (char **)&sample, 10);
-			if (outminute) *outminute = component;
-		}
-
-		/*get the second*/ {
-			while (*sample && (*sample < '0' || *sample > '9')) ++sample;
-			if (!*sample) {
-				success = NO;
-				goto fail;
-			}
-			component = strtoul(sample, (char **)&sample, 10);
-			if (outsecond) *outsecond = component;
-		}
-
-		/*get the time zone*/ {
-			while (*sample && ((*sample < '0' || *sample > '9') && *sample != '-' && *sample != '+')) ++sample;
-			if (!*sample) {
-				success = NO;
-				goto fail;
-			}
-			long timezone_sign = 1;
-			if(*sample == '+') {
-				++sample;
-			} else if(*sample == '-') {
-				timezone_sign = -1;
-				++sample;
-			} else if (*sample) {
-				//There's something here, but it's not a time zone. Bail.
-				success = NO;
-				goto fail;
-			}
-			long timezone_hr = 0;
-			if (*sample >= '0' || *sample <= '9') {
-				timezone_hr += *(sample++) - '0';
-			}
-			if (*sample >= '0' || *sample <= '9') {
-				timezone_hr *= 10;
-				timezone_hr += *(sample++) - '0';
-			}
-			long timezone_min = 0;
-			if (*sample >= '0' || *sample <= '9') {
-				timezone_min += *(sample++) - '0';
-			}
-			if (*sample >= '0' || *sample <= '9') {
-				timezone_min *= 10;
-				timezone_min += *(sample++) - '0';
-			}
-			if (outtimezone) *outtimezone = (timezone_hr * 60 + timezone_min) * timezone_sign;
-		}
-	}
-	
-fail:
-	return success;
-}
--- a/UnitTests/TestScandate.h	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import <Cocoa/Cocoa.h>
-#import <SenTestingKit/SenTestingKit.h>
-
-@interface TestScandate : SenTestCase
-{}
-
-- (void) testEricRichiesTwitterTimelineLogFilename;
-
-@end
--- a/UnitTests/TestScandate.m	Wed Oct 30 18:34:07 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* 
- * Adium is the legal property of its developers, whose names are listed in the copyright file included
- * with this source distribution.
- * 
- * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
- * General Public License as published by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
- * Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with this program; if not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#import "TestScandate.h"
-
-#import "scandate.h"
-
-@implementation TestScandate
-
-- (void) testEricRichiesTwitterTimelineLogFilename {
-	static const char EricRichiesTwitterTimelineLogFilename[] = "timeline (edr1084) (2010-12-18T17.42.58-0500).chatlog";
-	unsigned long correctYear = 2010, correctMonth = 12, correctDayOfMonth = 18;
-	BOOL correctDidFindTime = YES;
-	unsigned long correctHour = 17, correctMinute = 42, correctSecond = 58;
-	long correctTimeZoneOffsetInMinutes = -(5 * 60);
-	BOOL correctDidFindDate = YES;
-
-	unsigned long foundYear, foundMonth, foundDayOfMonth;
-	BOOL didFindTime;
-	unsigned long foundHour, foundMinute, foundSecond;
-	long foundTimeZoneOffsetInMinutes;
-
-	BOOL didFindDate = scandate(EricRichiesTwitterTimelineLogFilename, &foundYear, &foundMonth, &foundDayOfMonth, &didFindTime, &foundHour, &foundMinute, &foundSecond, &foundTimeZoneOffsetInMinutes);
-	STAssertEquals(didFindDate, correctDidFindDate, @"No date found in this string! '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundYear, correctYear, @"Wrong year found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundMonth, correctMonth, @"Wrong month found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundDayOfMonth, correctDayOfMonth, @"Wrong day-of-month found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(didFindTime, correctDidFindTime, @"No time found in this string! '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundHour, correctHour, @"Wrong hour found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundMinute, correctMinute, @"Wrong minute found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundSecond, correctSecond, @"Wrong second found in '%s'", EricRichiesTwitterTimelineLogFilename);
-	STAssertEquals(foundTimeZoneOffsetInMinutes, correctTimeZoneOffsetInMinutes, @"Wrong time zone offset found in '%s'", EricRichiesTwitterTimelineLogFilename);
-}
-
-@end