Skip to content

Initial NSDateFormatter tests #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Foundation.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
2EBE67A51C77BF0E006583D5 /* TestNSDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBE67A31C77BF05006583D5 /* TestNSDateFormatter.swift */; };
528776141BF2629700CB0090 /* FoundationErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522C253A1BF16E1600804FC6 /* FoundationErrors.swift */; };
528776191BF27D9500CB0090 /* Test.plist in Resources */ = {isa = PBXBuildFile; fileRef = 528776181BF27D9500CB0090 /* Test.plist */; };
555683BD1C1250E70041D4C6 /* TestNSUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 555683BC1C1250E70041D4C6 /* TestNSUserDefaults.swift */; };
Expand Down Expand Up @@ -381,6 +382,7 @@

/* Begin PBXFileReference section */
22B9C1E01C165D7A00DECFF9 /* TestNSDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSDate.swift; sourceTree = "<group>"; };
2EBE67A31C77BF05006583D5 /* TestNSDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSDateFormatter.swift; sourceTree = "<group>"; };
400E22641C1A4E58007C5933 /* TestNSProcessInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSProcessInfo.swift; sourceTree = "<group>"; };
4AE109261C17CCBF007367B5 /* TestNSIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSIndexPath.swift; sourceTree = "<group>"; };
4DC1D07F1C12EEEF00B5948A /* TestNSPipe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSPipe.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1199,6 +1201,7 @@
A5A34B551C18C85D00FD972B /* TestNSByteCountFormatter.swift */,
D3047AEB1C38BC3300295652 /* TestNSValue.swift */,
E19E17DB1C2225930023AF4D /* TestNSXMLDocument.swift */,
2EBE67A31C77BF05006583D5 /* TestNSDateFormatter.swift */,
);
name = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1956,6 +1959,7 @@
5B13B3481C582D4C00651CE2 /* TestNSTimer.swift in Sources */,
5B13B32D1C582D4C00651CE2 /* TestNSDictionary.swift in Sources */,
5B13B3261C582D4C00651CE2 /* TestNSAffineTransform.swift in Sources */,
2EBE67A51C77BF0E006583D5 /* TestNSDateFormatter.swift in Sources */,
5B13B3291C582D4C00651CE2 /* TestNSCalendar.swift in Sources */,
5B13B34F1C582D4C00651CE2 /* TestNSXMLParser.swift in Sources */,
5B13B32F1C582D4C00651CE2 /* TestNSGeometry.swift in Sources */,
Expand Down
56 changes: 40 additions & 16 deletions Foundation/NSDateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@ public class NSDateFormatter : NSFormatter {
let dateStyle = CFDateFormatterStyle(self.dateStyle.rawValue)
let timeStyle = CFDateFormatterStyle(self.timeStyle.rawValue)
#endif

let obj = CFDateFormatterCreate(kCFAllocatorSystemDefault, locale._cfObject, dateStyle, timeStyle)
// TODO: Set up attributes here
if calendar != nil {
CFDateFormatterSetProperty(obj, kCFDateFormatterCalendar, calendar._cfObject)
}
CFDateFormatterSetProperty(obj, kCFDateFormatterTimeZone, timeZone._cfObject)
_setFormatterAttributes(obj)
if let dateFormat = _dateFormat {
CFDateFormatterSetFormat(obj, dateFormat._cfObject)
}
Expand All @@ -44,7 +41,7 @@ public class NSDateFormatter : NSFormatter {
super.init(coder: coder)
}

public var formattingContext: NSFormattingContext = .Unknown
public var formattingContext: NSFormattingContext = .Unknown // default is NSFormattingContextUnknown

public func objectValue(string: String, range rangep: UnsafeMutablePointer<NSRange>) throws -> AnyObject? { NSUnimplemented() }

Expand Down Expand Up @@ -90,6 +87,42 @@ public class NSDateFormatter : NSFormatter {
__cfObject = nil
}

internal func _setFormatterAttributes(formatter: CFDateFormatter) {
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterIsLenient, value: lenient._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterTimeZone, value: timeZone?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterCalendarName, value: calendar?.calendarIdentifier._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterTwoDigitStartDate, value: twoDigitStartDate?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterDefaultDate, value: defaultDate?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterCalendar, value: calendar?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterEraSymbols, value: eraSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterMonthSymbols, value: monthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortMonthSymbols, value: shortMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterWeekdaySymbols, value: weekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortWeekdaySymbols, value: shortWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterAMSymbol, value: AMSymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterPMSymbol, value: PMSymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterLongEraSymbols, value: longEraSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortMonthSymbols, value: veryShortMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneMonthSymbols, value: standaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneMonthSymbols, value: shortStandaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortStandaloneMonthSymbols, value: veryShortStandaloneMonthSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortWeekdaySymbols, value: veryShortWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneWeekdaySymbols, value: standaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneWeekdaySymbols, value: shortStandaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterVeryShortStandaloneWeekdaySymbols, value: veryShortStandaloneWeekdaySymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterQuarterSymbols, value: quarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortQuarterSymbols, value: shortQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterStandaloneQuarterSymbols, value: standaloneQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterShortStandaloneQuarterSymbols, value: shortStandaloneQuarterSymbols?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterGregorianStartDate, value: gregorianStartDate?._cfObject)
}

internal func _setFormatterAttribute(formatter: CFDateFormatter, attributeName: CFString, value: AnyObject?) {
if let value = value {
CFDateFormatterSetProperty(formatter, attributeName, value)
}
}

public var dateFormat: String! {
get {
guard let format = _dateFormat else {
Expand All @@ -107,16 +140,7 @@ public class NSDateFormatter : NSFormatter {

public var timeStyle: NSDateFormatterStyle = .NoStyle { willSet { _reset() } }

internal var _locale: NSLocale = NSLocale.currentLocale()
/*@NSCopying*/ public var locale: NSLocale! {
get {
return _locale
}
set {
_reset()
_locale = newValue
}
}
/*@NSCopying*/ public var locale: NSLocale! = .currentLocale() { willSet { _reset() } }

public var generatesCalendarDates = false { willSet { _reset() } }

Expand Down
178 changes: 178 additions & 0 deletions TestFoundation/TestNSDateFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//

#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
import Foundation
import XCTest
#else
import SwiftFoundation
import SwiftXCTest
#endif

class TestNSDateFormatter: XCTestCase {

let DEFAULT_LOCALE = "en_US"
let DEFAULT_TIMEZONE = "GMT"

static var allTests : [(String, TestNSDateFormatter -> () throws -> Void)] {
return [
("test_BasicConstruction", test_BasicConstruction),
// ("test_customDateFormat", test_customDateFormat),
("test_dateStyleShort", test_dateStyleShort),
("test_dateStyleMedium", test_dateStyleMedium),
("test_dateStyleLong", test_dateStyleLong),
("test_dateStyleFull", test_dateStyleFull)
]
}

func test_BasicConstruction() {
let f = NSDateFormatter()
XCTAssertNotNil(f)
}

func test_customDateFormat() {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = String("dd-MM-yyyy")
let dateStr = dateFormatter.stringFromDate(NSDate())

print("With dateFormat '\(dateFormatter.dateFormat)': '\(dateStr)'")

}

// ShortStyle
// locale stringFromDate example
// ------ -------------- --------
// en_US M/d/yy 12/25/15
func test_dateStyleShort() {

let timestamps = [
-31536000 : "1/1/69, 12:00 AM" , 0.0 : "1/1/70, 12:00 AM", 31536000 : "1/1/71, 12:00 AM",
2145916800 : "1/1/38, 12:00 AM", 1456272000 : "2/24/16, 12:00 AM", 1456358399 : "2/24/16, 11:59 PM",
1452574638 : "1/12/16, 4:57 AM", 1455685038 : "2/17/16, 4:57 AM", 1458622638 : "3/22/16, 4:57 AM",
1459745838 : "4/4/16, 4:57 AM", 1462597038 : "5/7/16, 4:57 AM", 1465534638 : "6/10/16, 4:57 AM",
1469854638 : "7/30/16, 4:57 AM", 1470718638 : "8/9/16, 4:57 AM", 1473915438 : "9/15/16, 4:57 AM",
1477285038 : "10/24/16, 4:57 AM", 1478062638 : "11/2/16, 4:57 AM", 1482641838 : "12/25/16, 4:57 AM"
]

let f = NSDateFormatter()
f.dateStyle = .ShortStyle
f.timeStyle = .ShortStyle

// ensure tests give consistent results by setting specific timeZone and locale
f.timeZone = NSTimeZone(name: DEFAULT_TIMEZONE)
f.locale = NSLocale(localeIdentifier: DEFAULT_LOCALE)

for (timestamp, stringResult) in timestamps {

let testDate = NSDate(timeIntervalSince1970: timestamp)
let sf = f.stringFromDate(testDate)

XCTAssertEqual(sf, stringResult)
}

}

// MediumStyle
// locale stringFromDate example
// ------ -------------- ------------
// en_US MMM d, y Dec 25, 2015
func test_dateStyleMedium() {

let timestamps = [
-31536000 : "Jan 1, 1969, 12:00:00 AM" , 0.0 : "Jan 1, 1970, 12:00:00 AM", 31536000 : "Jan 1, 1971, 12:00:00 AM",
2145916800 : "Jan 1, 2038, 12:00:00 AM", 1456272000 : "Feb 24, 2016, 12:00:00 AM", 1456358399 : "Feb 24, 2016, 11:59:59 PM",
1452574638 : "Jan 12, 2016, 4:57:18 AM", 1455685038 : "Feb 17, 2016, 4:57:18 AM", 1458622638 : "Mar 22, 2016, 4:57:18 AM",
1459745838 : "Apr 4, 2016, 4:57:18 AM", 1462597038 : "May 7, 2016, 4:57:18 AM", 1465534638 : "Jun 10, 2016, 4:57:18 AM",
1469854638 : "Jul 30, 2016, 4:57:18 AM", 1470718638 : "Aug 9, 2016, 4:57:18 AM", 1473915438 : "Sep 15, 2016, 4:57:18 AM",
1477285038 : "Oct 24, 2016, 4:57:18 AM", 1478062638 : "Nov 2, 2016, 4:57:18 AM", 1482641838 : "Dec 25, 2016, 4:57:18 AM"
]

let f = NSDateFormatter()
f.dateStyle = .MediumStyle
f.timeStyle = .MediumStyle
f.timeZone = NSTimeZone(name: DEFAULT_TIMEZONE)
f.locale = NSLocale(localeIdentifier: DEFAULT_LOCALE)

for (timestamp, stringResult) in timestamps {

let testDate = NSDate(timeIntervalSince1970: timestamp)
let sf = f.stringFromDate(testDate)

XCTAssertEqual(sf, stringResult)
}

}


// LongStyle
// locale stringFromDate example
// ------ -------------- -----------------
// en_US MMMM d, y December 25, 2015
func test_dateStyleLong() {

let timestamps = [
-31536000 : "January 1, 1969 at 12:00:00 AM GMT" , 0.0 : "January 1, 1970 at 12:00:00 AM GMT", 31536000 : "January 1, 1971 at 12:00:00 AM GMT",
2145916800 : "January 1, 2038 at 12:00:00 AM GMT", 1456272000 : "February 24, 2016 at 12:00:00 AM GMT", 1456358399 : "February 24, 2016 at 11:59:59 PM GMT",
1452574638 : "January 12, 2016 at 4:57:18 AM GMT", 1455685038 : "February 17, 2016 at 4:57:18 AM GMT", 1458622638 : "March 22, 2016 at 4:57:18 AM GMT",
1459745838 : "April 4, 2016 at 4:57:18 AM GMT", 1462597038 : "May 7, 2016 at 4:57:18 AM GMT", 1465534638 : "June 10, 2016 at 4:57:18 AM GMT",
1469854638 : "July 30, 2016 at 4:57:18 AM GMT", 1470718638 : "August 9, 2016 at 4:57:18 AM GMT", 1473915438 : "September 15, 2016 at 4:57:18 AM GMT",
1477285038 : "October 24, 2016 at 4:57:18 AM GMT", 1478062638 : "November 2, 2016 at 4:57:18 AM GMT", 1482641838 : "December 25, 2016 at 4:57:18 AM GMT"
]

let f = NSDateFormatter()
f.dateStyle = .LongStyle
f.timeStyle = .LongStyle
f.timeZone = NSTimeZone(name: DEFAULT_TIMEZONE)
f.locale = NSLocale(localeIdentifier: DEFAULT_LOCALE)

for (timestamp, stringResult) in timestamps {

let testDate = NSDate(timeIntervalSince1970: timestamp)
let sf = f.stringFromDate(testDate)

XCTAssertEqual(sf, stringResult)
}

}

// FullStyle
// locale stringFromDate example
// ------ -------------- -------------------------
// en_US EEEE, MMMM d, y Friday, December 25, 2015
func test_dateStyleFull() {

let timestamps = [
-31536000 : "Wednesday, January 1, 1969 at 12:00:00 AM GMT" , 0.0 : "Thursday, January 1, 1970 at 12:00:00 AM GMT",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the correct value be Greenwich Mean Time instead of GMT?

That's what ICU spec says (http://userguide.icu-project.org/formatparse/datetime)
Also, that's the behaviour of f.timeStyle = .full on macOS.

It appears that for negative timestampts (e.g. -31536000) DateFormatter on macOS wrongly returns GMT instead of Greenwich Mean Time, which seems to be a bug.

31536000 : "Friday, January 1, 1971 at 12:00:00 AM GMT", 2145916800 : "Friday, January 1, 2038 at 12:00:00 AM GMT",
1456272000 : "Wednesday, February 24, 2016 at 12:00:00 AM GMT", 1456358399 : "Wednesday, February 24, 2016 at 11:59:59 PM GMT",
1452574638 : "Tuesday, January 12, 2016 at 4:57:18 AM GMT", 1455685038 : "Wednesday, February 17, 2016 at 4:57:18 AM GMT",
1458622638 : "Tuesday, March 22, 2016 at 4:57:18 AM GMT", 1459745838 : "Monday, April 4, 2016 at 4:57:18 AM GMT",
1462597038 : "Saturday, May 7, 2016 at 4:57:18 AM GMT", 1465534638 : "Friday, June 10, 2016 at 4:57:18 AM GMT",
1469854638 : "Saturday, July 30, 2016 at 4:57:18 AM GMT", 1470718638 : "Tuesday, August 9, 2016 at 4:57:18 AM GMT",
1473915438 : "Thursday, September 15, 2016 at 4:57:18 AM GMT", 1477285038 : "Monday, October 24, 2016 at 4:57:18 AM GMT",
1478062638 : "Wednesday, November 2, 2016 at 4:57:18 AM GMT", 1482641838 : "Sunday, December 25, 2016 at 4:57:18 AM GMT"
]

let f = NSDateFormatter()
f.dateStyle = .FullStyle
f.timeStyle = .FullStyle
f.timeZone = NSTimeZone(name: DEFAULT_TIMEZONE)
f.locale = NSLocale(localeIdentifier: DEFAULT_LOCALE)

for (timestamp, stringResult) in timestamps {

let testDate = NSDate(timeIntervalSince1970: timestamp)
let sf = f.stringFromDate(testDate)

XCTAssertEqual(sf, stringResult)
}

}

}
1 change: 1 addition & 0 deletions TestFoundation/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ XCTMain([
testCase(TestNSCharacterSet.allTests),
testCase(TestNSData.allTests),
testCase(TestNSDate.allTests),
testCase(TestNSDateFormatter.allTests),
testCase(TestNSDictionary.allTests),
testCase(TestNSFileManger.allTests),
testCase(TestNSGeometry.allTests),
Expand Down