--- /dev/null
+//===--- NSDateFormatterCheck.cpp - clang-tidy ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "NSDateFormatterCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace objc {
+
+void NSDateFormatterCheck::registerMatchers(MatchFinder *Finder) {
+ // Adding matchers.
+
+ Finder->addMatcher(
+ objcMessageExpr(hasSelector("setDateFormat:"),
+ hasReceiverType(asString("NSDateFormatter *")),
+ hasArgument(0, ignoringImpCasts(
+ objcStringLiteral().bind("str_lit")))),
+ this);
+}
+
+static char ValidDatePatternChars[] = {
+ 'G', 'y', 'Y', 'u', 'U', 'r', 'Q', 'q', 'M', 'L', 'I', 'w', 'W', 'd',
+ 'D', 'F', 'g', 'E', 'e', 'c', 'a', 'b', 'B', 'h', 'H', 'K', 'k', 'j',
+ 'J', 'C', 'm', 's', 'S', 'A', 'z', 'Z', 'O', 'v', 'V', 'X', 'x'};
+
+// Checks if the string pattern used as a date format specifier is valid.
+// A string pattern is valid if all the letters(a-z, A-Z) in it belong to the
+// set of reserved characters. See:
+// https://www.unicode.org/reports/tr35/tr35.html#Invalid_Patterns
+bool isValidDatePattern(StringRef Pattern) {
+ for (auto &PatternChar : Pattern) {
+ if (isalpha(PatternChar)) {
+ if (std::find(std::begin(ValidDatePatternChars),
+ std::end(ValidDatePatternChars),
+ PatternChar) == std::end(ValidDatePatternChars)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Checks if the string pattern used as a date format specifier contains
+// any incorrect pattern and reports it as a warning.
+// See: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
+void NSDateFormatterCheck::check(const MatchFinder::MatchResult &Result) {
+ // Callback implementation.
+ const auto *StrExpr = Result.Nodes.getNodeAs<ObjCStringLiteral>("str_lit");
+ const StringLiteral *SL = cast<ObjCStringLiteral>(StrExpr)->getString();
+ StringRef SR = SL->getString();
+
+ if (!isValidDatePattern(SR)) {
+ diag(StrExpr->getExprLoc(), "invalid date format specifier");
+ }
+
+ if (SR.contains('y') && SR.contains('w') && !SR.contains('Y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of calendar year (y) with week of the year (w); "
+ "did you mean to use week-year (Y) instead?");
+ }
+ if (SR.contains('F')) {
+ if (!(SR.contains('e') || SR.contains('E'))) {
+ diag(StrExpr->getExprLoc(),
+ "day of week in month (F) used without day of the week (e or E); "
+ "did you forget e (or E) in the format string?");
+ }
+ if (!SR.contains('M')) {
+ diag(StrExpr->getExprLoc(),
+ "day of week in month (F) used without the month (M); "
+ "did you forget M in the format string?");
+ }
+ }
+ if (SR.contains('W') && !SR.contains('M')) {
+ diag(StrExpr->getExprLoc(), "Week of Month (W) used without the month (M); "
+ "did you forget M in the format string?");
+ }
+ if (SR.contains('Y') && SR.contains('Q') && !SR.contains('y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of week year (Y) with quarter number (Q); "
+ "did you mean to use calendar year (y) instead?");
+ }
+ if (SR.contains('Y') && SR.contains('M') && !SR.contains('y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of week year (Y) with month (M); "
+ "did you mean to use calendar year (y) instead?");
+ }
+ if (SR.contains('Y') && SR.contains('D') && !SR.contains('y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of week year (Y) with day of the year (D); "
+ "did you mean to use calendar year (y) instead?");
+ }
+ if (SR.contains('Y') && SR.contains('W') && !SR.contains('y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of week year (Y) with week of the month (W); "
+ "did you mean to use calendar year (y) instead?");
+ }
+ if (SR.contains('Y') && SR.contains('F') && !SR.contains('y')) {
+ diag(StrExpr->getExprLoc(),
+ "use of week year (Y) with day of the week in month (F); "
+ "did you mean to use calendar year (y) instead?");
+ }
+}
+
+} // namespace objc
+} // namespace tidy
+} // namespace clang
--- /dev/null
+.. title:: clang-tidy - objc-nsdate-formatter
+
+objc-nsdate-formatter
+=====================
+
+When ``NSDateFormatter`` is used to convert an ``NSDate`` type to a ``String`` type, the user
+can specify a custom format string. Certain format specifiers are undesirable
+despite being legal. See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns for all legal date patterns.
+
+This checker reports as warnings the following string patterns in a date format specifier:
+
+#. yyyy + ww : Calendar year specified with week of a week year (unless YYYY is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `yyyy-ww`;
+ | Output string: `2014-01` (Wrong because it’s not the first week of 2014)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `dd-MM-yyyy (ww-YYYY)`;
+ | Output string: `29-12-2014 (01-2015)` (This is correct)
+
+#. F without ee/EE : Numeric day of week in a month without actual day.
+
+ * | **Example:** Input Date: `29 December 2014` ; Format String: `F-MM`;
+ | Output string: `5-12` (Wrong because it reads as *5th ___ of Dec* in English)
+
+#. F without MM : Numeric day of week in a month without month.
+
+ * | **Example:** Input Date: `29 December 2014` ; Format String: `F-EE`
+ | Output string: `5-Mon` (Wrong because it reads as *5th Mon of ___* in English)
+
+#. WW without MM : Week of the month without the month.
+
+ * | **Example:** Input Date: `29 December 2014` ; Format String: `WW-yyyy`
+ | Output string: `05-2014` (Wrong because it reads as *5th Week of ___* in English)
+
+#. YYYY + QQ : Week year specified with quarter of normal year (unless yyyy is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-QQ`
+ | Output string: `2015-04` (Wrong because it’s not the 4th quarter of 2015)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (QQ-yyyy)`
+ | Output string: `01-2015 (04-2014)` (This is correct)
+
+#. YYYY + MM : Week year specified with Month of a calendar year (unless yyyy is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-MM`
+ | Output string: `2015-12` (Wrong because it’s not the 12th month of 2015)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (MM-yyyy)`
+ | Output string: `01-2015 (12-2014)` (This is correct)
+
+#. YYYY + DD : Week year with day of a calendar year (unless yyyy is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-DD`
+ | Output string: `2015-363` (Wrong because it’s not the 363rd day of 2015)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (DD-yyyy)`
+ | Output string: `01-2015 (363-2014)` (This is correct)
+
+#. YYYY + WW : Week year with week of a calendar year (unless yyyy is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-WW`
+ | Output string: `2015-05` (Wrong because it’s not the 5th week of 2015)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (WW-MM-yyyy)`
+ | Output string: `01-2015 (05-12-2014)` (This is correct)
+
+#. YYYY + F : Week year with day of week in a calendar month (unless yyyy is also specified).
+
+ * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-ww-F-EE`
+ | Output string: `2015-01-5-Mon` (Wrong because it’s not the 5th Monday of January in 2015)
+
+ * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (F-EE-MM-yyyy)`
+ | Output string: `01-2015 (5-Mon-12-2014)` (This is correct)
--- /dev/null
+// RUN: %check_clang_tidy %s objc-nsdate-formatter %t
+@interface NSObject
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface TestClass : NSObject
++ (void)testMethod1;
++ (void)testMethod2;
++ (void)testMethod3;
++ (void)testAnotherClass;
+@end
+
+@interface NSString : NSObject
+@end
+
+void NSLog(NSString *format, ...);
+
+@interface NSDate : NSObject
+@end
+
+@interface NSDateFormatter : NSObject
+@property(copy) NSString *dateFormat;
+- (NSString *)stringFromDate:(NSDate *)date;
+@end
+
+@interface AnotherClass : NSObject
+@property(copy) NSString *dateFormat;
+@end
+
+@interface NSDateComponents : NSObject
+@property long year;
+@property long month;
+@property long day;
+@end
+
+@interface NSCalendar : NSObject
+@property(class, readonly, copy) NSCalendar *currentCalendar;
+- (nullable NSDate *)dateFromComponents:(NSDateComponents *)Comps;
+@end
+
+@implementation TestClass
++ (void)testMethod1 {
+ // Reproducing incorrect behavior from Radar
+ NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+ [formatter setDateFormat:@"YYYY_MM_dd_HH_mm_ss_SSS_ZZZ"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSDateComponents *comps = [[NSDateComponents alloc] init];
+ [comps setDay:29];
+ [comps setMonth:12];
+ [comps setYear:2014];
+ NSDate *date_radar = [[NSCalendar currentCalendar] dateFromComponents:comps];
+ NSLog(@"YYYY_MM_dd_HH_mm_ss_SSS_ZZZ %@", [formatter stringFromDate:date_radar]);
+
+ // Radar correct behavior
+ [formatter setDateFormat:@"yyyy_MM_dd_HH_mm_ss_SSS_ZZZ"];
+ NSLog(@"yyyy_MM_dd_HH_mm_ss_SSS_ZZZ %@", [formatter stringFromDate:date_radar]);
+
+ // Radar correct behavior - week year
+ [formatter setDateFormat:@"YYYY_ww_dd_HH_mm_ss_SSS_ZZZ"];
+ NSLog(@"YYYY_ww_dd_HH_mm_ss_SSS_ZZZ %@", [formatter stringFromDate:date_radar]);
+
+ // Radar incorrect behavior
+ [formatter setDateFormat:@"yyyy_ww_dd_HH_mm_ss_SSS_ZZZ"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_ww_dd_HH_mm_ss_SSS_ZZZ %@", [formatter stringFromDate:date_radar]);
+
+ NSLog(@"==========================================");
+ // Correct
+ [formatter setDateFormat:@"yyyy_MM"];
+ NSLog(@"yyyy_MM %@", [formatter stringFromDate:date_radar]);
+
+ // Correct
+ [formatter setDateFormat:@"yyyy_dd"];
+ NSLog(@"yyyy_dd %@", [formatter stringFromDate:date_radar]);
+
+ // Correct
+ [formatter setDateFormat:@"yyyy_DD"];
+ NSLog(@"yyyy_DD %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"yyyy_ww"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_ww %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"yyyy_WW"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: Week of Month (W) used without the month (M); did you forget M in the format string? [objc-nsdate-formatter]
+ NSLog(@"yyyy_WW %@", [formatter stringFromDate:date_radar]);
+
+ NSLog(@"==========================================");
+ // Correct
+ [formatter setDateFormat:@"yyyy_MM_dd"];
+ NSLog(@"yyyy_MM_dd %@", [formatter stringFromDate:date_radar]);
+
+ // Potentially Incorrect
+ [formatter setDateFormat:@"yyyy_MM_DD"];
+ NSLog(@"yyyy_MM_DD %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"yyyy_MM_ww"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_MM_ww %@", [formatter stringFromDate:date_radar]);
+
+ NSLog(@"=======WEEK YEAR==========");
+ // Incorrect
+ [formatter setDateFormat:@"YYYY_MM"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_MM %@", [formatter stringFromDate:date_radar]);
+
+ // Correct
+ [formatter setDateFormat:@"YYYY_ww"];
+ NSLog(@"YYYY_ww %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"YYYY_WW"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: Week of Month (W) used without the month (M); did you forget M in the format string? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_WW %@", [formatter stringFromDate:date_radar]);
+
+ // Correct
+ [formatter setDateFormat:@"YYYY_dd"];
+ NSLog(@"YYYY_dd %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"YYYY_DD"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_DD %@", [formatter stringFromDate:date_radar]);
+
+ NSLog(@"==========================================");
+ // Potentially Incorrect
+ [formatter setDateFormat:@"YYYY_ww_dd"];
+ NSLog(@"YYYY ww dd %@", [formatter stringFromDate:date_radar]);
+
+ // Incorrect
+ [formatter setDateFormat:@"YYYY_ww_DD"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_ww_DD %@", [formatter stringFromDate:date_radar]);
+}
+
++ (void)testMethod2 {
+ NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+ NSDateComponents *comps = [[NSDateComponents alloc] init];
+ [comps setDay:29];
+ [comps setMonth:12];
+ [comps setYear:2014];
+ NSDate *date_radar = [[NSCalendar currentCalendar] dateFromComponents:comps];
+
+ // Test 1 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_dd_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_dd_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 2 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_dd_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_dd_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 3 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_DD_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_DD_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 4 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_DD_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_DD_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 5 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_F_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_F_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 6 : incorrect
+ [formatter setDateFormat:@"yyyy_QQ_MM_ww_F_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of calendar year (y) with week of the year (w); did you mean to use week-year (Y) instead? [objc-nsdate-formatter]
+ NSLog(@"yyyy_QQ_MM_ww_F_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 7 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_dd_EE"];
+ NSLog(@"yyyy_QQ_MM_WW_dd_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 8 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_dd_ee"];
+ NSLog(@"yyyy_QQ_MM_WW_dd_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 9 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_DD_EE"];
+ NSLog(@"yyyy_QQ_MM_WW_DD_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 10 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_DD_ee"];
+ NSLog(@"yyyy_QQ_MM_WW_DD_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 11 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_F_EE"];
+ NSLog(@"yyyy_QQ_MM_WW_F_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 12 : correct
+ [formatter setDateFormat:@"yyyy_QQ_MM_WW_F_ee"];
+ NSLog(@"yyyy_QQ_MM_WW_F_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 13 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_dd_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_dd_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 14 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_dd_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_dd_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 15 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_DD_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_DD_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 16 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_DD_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_DD_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 17 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_F_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the week in month (F); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_F_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 18 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_ww_F_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the week in month (F); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_ww_F_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 19 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_dd_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_dd_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 20 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_dd_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_dd_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 21 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_DD_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-4]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_DD_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 22 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_DD_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the year (D); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-4]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_DD_ee %@", [formatter stringFromDate:date_radar]);
+
+ // Test 23 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_F_EE"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the week in month (F); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-4]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_F_EE %@", [formatter stringFromDate:date_radar]);
+
+ // Test 24 : incorrect
+ [formatter setDateFormat:@"YYYY_QQ_MM_WW_F_ee"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use of week year (Y) with day of the week in month (F); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of week year (Y) with month (M); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-3]]:28: warning: use of week year (Y) with quarter number (Q); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ // CHECK-MESSAGES: :[[@LINE-4]]:28: warning: use of week year (Y) with week of the month (W); did you mean to use calendar year (y) instead? [objc-nsdate-formatter]
+ NSLog(@"YYYY_QQ_MM_WW_F_ee %@", [formatter stringFromDate:date_radar]);
+}
+
++ (void)testMethod3 {
+ NSDateFormatter *Formatter = [[NSDateFormatter alloc] init];
+ NSDateComponents *Comps = [[NSDateComponents alloc] init];
+ [Comps setDay:29];
+ [Comps setMonth:12];
+ [Comps setYear:2014];
+ NSDate *DateRadar = [[NSCalendar currentCalendar] dateFromComponents:Comps];
+
+ // Incorrect : has reserved and invalid chars
+ [Formatter setDateFormat:@"Rashmi"];
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: invalid date format specifier [objc-nsdate-formatter]
+ NSLog(@"Rashmi %@", [Formatter stringFromDate:DateRadar]);
+
+ // Correct
+ [Formatter setDateFormat:@"AMy"];
+ NSLog(@"AMy %@", [Formatter stringFromDate:DateRadar]);
+}
+
++ (void)testAnotherClass {
+ AnotherClass *Formatter = [[AnotherClass alloc] init];
+ [Formatter setDateFormat:@"RandomString"];
+ [Formatter setDateFormat:@"YYYY_QQ_MM_WW_dd_EE"];
+}
+@end