Repository: translate/pootle

Issue:
Checks: fix and simplify date_format check
There is `date_format` check in pootle checks which is false positive on 
https://translate.evernote.com/cs/web_evernote/translate/gwt/com/evernote/web/gwt/client/v2/i18n/FocusMessages.properties.po#unit=4304702

```
source: EEE, MMM d h:mm a
target: EEE, MMM d HH:mm
```

This check assumes too much.
https://github.com/translate/pootle/blob/8379a35b/pootle/apps/pootle_misc/checks.py#L161-L169

Let's make it to check if a target corresponds to the format described [here](http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html).

Checks: fix and simplify date_format check
There is `date_format` check in pootle checks which is false positive on 
https://translate.evernote.com/cs/web_evernote/translate/gwt/com/evernote/web/gwt/client/v2/i18n/FocusMessages.properties.po#unit=4304702

```
source: EEE, MMM d h:mm a
target: EEE, MMM d HH:mm
```

This check assumes too much.
https://github.com/translate/pootle/blob/8379a35b/pootle/apps/pootle_misc/checks.py#L161-L169

Let's make it to check if a target corresponds to the format described [here](http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html).



Discussion:

Resolving patch:
diff --git a/pootle/apps/pootle_misc/checks.py b/pootle/apps/pootle_misc/checks.py
--- a/pootle/apps/pootle_misc/checks.py
+++ b/pootle/apps/pootle_misc/checks.py
@@ -165,15 +165,17 @@
 fmt = u"\{{2}[\/]?[^\}]+\}{2}"
 mustache_like_placeholder_pairs_regex = re.compile(u"(%s)" % fmt, re.U)
 
-date_format_regex_0 = re.compile(u"^([GyMwWDdFEaHkKhmsSzZ]+[^\w]*)+$", re.U)
-date_format_regex_1 = re.compile(u"^(Day|Days|May|SMS|M|S|W|F|add|ads)$", re.I|re.U)
-date_format_regex_2 = re.compile(u"^(h:mm a|h:mm aa|hh:mm a|hh:mm aa)$", re.U)
-date_format_regex_3 = re.compile(u"^(H:mm|HH:mm)$", re.U)
-date_format_regex_4 = re.compile(u"^EEEE, MMMM d yyyy, (h:mm a|h:mm aa|hh:mm a|hh:mm aa)$", re.U)
-date_format_regex_5 = re.compile(u"^(EEEE, MMMM d yyyy|EEEE, d MMMM yyyy), (H:mm|HH:mm)$", re.U)
-date_format_regex_6 = re.compile(u"^MMMM yyyy$", re.U)
-date_format_regex_7 = re.compile(u"^yyyy'年'MMMM$", re.U)
-date_format_regex_8 = re.compile(u"[^\w]+", re.U)
+# date_format
+df_blocks = u"|".join(map(lambda x: '%s+' % x, 'GyYMwWDdFEuaHkKhmsSzZX')) + u"|\'[\w]+\'"
+df_glued_blocks = u"X+|Z+|\'[\w]*\'"
+df_delimiter = u"[^\w']+|\'[\w]*\'"
+df_regex_str = u"^(%(blocks)s)(%(glued_blocks)s)?((%(delimiter)s)+(%(blocks)s))*$" % {
+    'blocks': df_blocks,
+    'glued_blocks': df_glued_blocks,
+    'delimiter': df_delimiter,
+}
+date_format_regex = re.compile(df_regex_str, re.U)
+date_format_exception_regex = re.compile(u"^(M|S|W|F)$", re.I|re.U)
 
 fmt = u"^\s+|\s+$"
 whitespace_regex = re.compile(u"(%s)" % fmt, re.U)
@@ -417,30 +419,16 @@ def get_fingerprint(str, is_source=False, translation=''):
     @critical
     def date_format(self, str1, str2):
         def get_fingerprint(str, is_source=False, translation=''):
+            is_date_format = bool(date_format_regex.match(str))
             if is_source:
-                if not date_format_regex_0.match(str):
+                if not is_date_format:
                     raise SkipCheck()
 
                 # filter out specific English strings which are not dates
-                if date_format_regex_1.match(str):
+                if date_format_exception_regex.match(str):
                     raise SkipCheck()
 
-                # filter out specific translation pairs
-                if date_format_regex_2.match(str):
-                    if date_format_regex_3.match(translation):
-                        raise SkipCheck()
-
-                if date_format_regex_4.match(str):
-                    if date_format_regex_5.match(translation):
-                        raise SkipCheck()
-
-                if date_format_regex_6.match(str):
-                    if date_format_regex_7.match(translation):
-                        raise SkipCheck()
-
-            fingerprint = u"\001".join(sorted(date_format_regex_8.split(str)))
-
-            return fingerprint
+            return is_date_format
 
         if check_translation(get_fingerprint, str1, str2):
             return True


Test patch:
diff --git a/tests/misc/checks.py b/tests/misc/checks.py
--- a/tests/misc/checks.py
+++ b/tests/misc/checks.py
@@ -227,3 +227,30 @@ def test_broken_entities():
     ]
 
     do_test(check, tests)
+
+
+def test_date_format():
+    check = checker.date_format
+    tests = [
+        (u"EEE, MMM d h:mm a", u"EEE, MMM d HH:mm", True),
+        (u"EEE, MMM", u"EEEMMM", False),
+        (u"yyyy.MM.dd G 'at' HH:mm:ss z", u"yyyy.MM.dd G 'в' HH:mm:ss z", True),
+        (u"EEE, MMM d, ''yy", u"dd-MM-yy", True),
+        (u"h:mm a", u"dd-MM-yy", True),
+        (u"hh 'o''clock' a, zzzz", u"dd-MM-yy", True),
+        (u"K:mm a, z", u"dd-MM-yy", True),
+        (u"yyyyy.MMMMM.dd GGG hh:mm aaa", u"dd-MM-yy", True),
+        (u"EEE, d MMM yyyy HH:mm:ss Z", u"dd-MM-yy", True),
+        (u"yyyy-MM-dd'T'HH:mm:ss.SSSZ", u"dd-MM-yy", True),
+        (u"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", u"dd-MM-yy", True),
+        (u"YYYY-'W'ww-u", u"dd-MM-yy", True),
+
+        # if a string isn't a date_format string the check should be skipped
+        (u"yyMMddHHmmssZ", u"what ever 345", True),
+        (u"F", u"what ever 345", True),
+        (u"M", u"what ever 345", True),
+        (u"S", u"what ever 345", True),
+        (u"W", u"what ever 345", True),
+    ]
+
+    do_test(check, tests)