如何编写正则表达式来识别 android 中字符串的不同日期模式?

How to write regex to identify different date patterns of a String in android?

我在 API 秒内收到不同的日期模式。有什么方法可以识别 API 中接收到的字符串的日期模式,以便我可以在不引发任何日期异常的情况下格式化它们?

使用此字符串扩展函数来识别字符串的日期模式。

/**
 * Created By Sweta 
 *  *  Method to check Input Date Pattern Before before Formatting
 * @param outputPattern This parameter takes the output DATE Pattern as String
 *  Checks four patterns: "dd/mm/yyyy", "mm/dd/yyyy hh:MM:ss", "dd MMM yyyy", "yyyy-MM-dd",
 *  "yyyy-MM-dd'T'HH:mm:ss", "dd-MMM-yyyy", "MM/dd/yyyy hh:mm:ss a", "dd-mm-yyyy hh:mm:ss",
 *  "dd-mm-yyyy hh:mm:ss a", "mm/dd/yyyy hh:mm:ss", "mm/dd/yyyy"
 */
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
fun String.checkInputDatePatternBefore(outputPattern: String): String {

    //"dd/mm/yyyy"
    val regex1 = "^(3[01]|[12][0-9]|0[1-9]|[1-9])/(1[0-2]|0[1-9]|[1-9])/[0-9]{4}$".toRegex()
    
    //"mm/dd/yyyy hh:MM:ss"
    val regex2 =
        "^(1[0-2]|0[1-9]|[1-9])/(3[01]|[12][0-9]|0[1-9]|[1-9])/[0-9]{4} [0-9][0-9]:([0]?[0-5] 
    [0-9]|[0-9]):([0-5][0-9])$"
            .toRegex()

    //"dd MMM yyyy"
    val regex3 = "(3[01]|[12][0-9]|0[1-9]|[1-9])[\s][a-zA-Z]{3}[\s][0-9]{4}$".toRegex()
   
    //"yyyy-MM-dd"
    val regex4 =
        "([0-9]{4})[\-](1[0-2]|0[1-9]|[1-9])[\-](3[01]|[12][0-9]|0[1-9]|[1-9])$".toRegex()
    //"yyyy-MM-dd'T'HH:mm:ss"
   
   val regex5 =
        "([0-9]{4})[\-](1[0-2]|0[1-9]|[1-9])[\-](3[01]|[12][0-9]|0[1-9])[T][0-9][0-9]:([0]? 
   [0-5][0-9]|[0-9]):([0-5][0-9])$".toRegex()

    //"dd-MMM-yyyy"
    val regex6 = "(3[01]|[12][0-9]|0[1-9]|[1-9])[\-][a-zA-Z]{3}[\-][0-9]{4}$".toRegex()

    //"MM/dd/yyyy hh:mm:ss a"
    val regex7 =
        "^((1[0-2]|0[1-9]|[1-9])/3[01]|[12][0-9]|0[1-9]|[1-9])/[0-9]{4}[\s][0-9][0-9]:([0]? 
   [0-5][0-9]|[0-9]):([0-5][0-9])[\s][a-zA-Z]{2}$"
            .toRegex()

    //28-02-2022 12:12:24
    //"dd-mm-yyyy hh:mm:ss"
    val regex8 =
        "(3[01]|[12][0-9]|0[1-9]|[1-9])[\-](1[0-2]|0[1-9]|[1-9])[\-][0-9]{4}[\s][0-9][0-9]: 
  ([0]?[0-5][0-9]|[0-9]):([0-5][0-9])$".toRegex()
  
   //"dd-mm-yyyy hh:mm:ss a"
    val regex9 =
        "(3[01]|[12][0-9]|0[1-9]|[1-9])[\-](1[0-2]|0[1-9]|[1-9])[\-][0-9]{4}[\s][0-9][0-9]: 
   ([0]?[0-5][0-9]|[0-9]):([0-5][0-9])[\s][a-zA-Z]{2}$".toRegex()
  
   //"mm/dd/yyyy hh:mm:ss"
    val regex10 =
        "(1[0-2]|0[1-9]|[1-9])[/](3[01]|[12][0-9]|0[1-9]|[1-9])[/][0-9]{4}[\s][0-9][0-9]: 
   ([0]?[0-5][0-9]|[0-9]):([0-5][0-9])$"
            .toRegex()
   
   //"mm/dd/yyyy"
    val regex11 =
        "(1[0-2]|0[1-9]|[1-9])[/](3[01]|[12][0-9]|0[1-9]|[1-9])[/][0-9]{4}$"
            .toRegex()


    val bool1: Boolean = regex1.matches(this)
    val bool2: Boolean = regex2.matches(this)
    val bool3: Boolean = regex3.matches(this)
    val bool4: Boolean = regex4.matches(this)
    val bool5: Boolean = regex5.matches(this)
    val bool6: Boolean = regex6.matches(this)
    val bool7: Boolean = regex7.matches(this)
    val bool8: Boolean = regex8.matches(this)
    val bool9: Boolean = regex9.matches(this)
    val bool10: Boolean = regex10.matches(this)
    val bool11: Boolean = regex11.matches(this)

    when {
        bool1 -> {
            Log.d(TAG, "Pattern dd/mm/yyyy")
            return "Pattern dd/mm/yyyy"
        }
        bool2 -> {
            Log.d(TAG, "Pattern mm/dd/yyyy hh:MM:ss")
            return "Pattern mm/dd/yyyy hh:MM:ss"
        }
        bool3 -> {
            Log.d(TAG, "Pattern dd MMM yyyy")
            return "Pattern dd MMM yyyy"
        }
        bool4 -> {
            Log.d(TAG, "Pattern yyyy-MM-dd")
            return "Pattern yyyy-MM-dd"
        }
        bool5 -> {
            Log.d(TAG, "Pattern yyyy-MM-dd'T'HH:mm:ss")
            return "Pattern yyyy-MM-dd'T'HH:mm:ss"
        }
        bool6 -> {
            Log.d(TAG, "Pattern dd-MMM-yyyy")
            return "Pattern dd-MMM-yyyy"
        }
        bool7 -> {
            Log.d(TAG, "Pattern MM/dd/yyyy hh:mm:ss a")
            return "Pattern MM/dd/yyyy hh:mm:ss a"
        }
        bool8 -> {
            Log.d(TAG, "Pattern dd-mm-yyyy hh:mm:ss")
            return "Pattern dd-mm-yyyy hh:mm:ss"
        }
        bool9 -> {
            Log.d(TAG, "Pattern dd-mm-yyyy hh:mm:ss AM/PM")
            return "Pattern dd-mm-yyyy hh:mm:ss AM/PM"
        }
        bool10 -> {
            Log.d(TAG, "Pattern mm/dd/yyyy hh:mm:ss")
            return "Pattern mm/dd/yyyy hh:mm:ss"
        }
        bool11 -> {
            Log.d(TAG, "Pattern mm/dd/yyyy")
            return "Pattern mm/dd/yyyy"
        }
        else -> {
            Log.d(TAG, "Date pattern not recognized!")
            Log.d(TAG, this)
            return "Date pattern not recognized!"
        }
    }
}

提供 的替代实现。代码审查时间! (不包括此方法或正则表达式的正确性。)

大部分代码的重复性本应暗示它需要重构。除了正则表达式定义之外的所有内容都只是重复的块,例如:

val bool1: Boolean = regex1.matches(this)
val bool2: Boolean = regex2.matches(this)
...
val bool11: Boolean = regex11.matches(this)

还有

when {
    bool1 -> {
        Log.d(TAG, "Pattern dd/mm/yyyy")
        return "Pattern dd/mm/yyyy"
    }
    bool2 -> {
        Log.d(TAG, "Pattern mm/dd/yyyy hh:MM:ss")
        return "Pattern mm/dd/yyyy hh:MM:ss"
    }
    ...
}

表单相同,但变量和消息不同。并且按照当前的逻辑,在第一次匹配时停止。如果添加了新的正则表达式,则需要在 when.

中添加更多 val bool12/13/14/15 和更多检查

相反,将所有内容放入一个集合中,如 List。并将日期格式与正则表达式相关联,在 Map. 完成这两项更改后,唯一剩下的就是必须定义的正则表达式。您还可以使用相关方法将每个模式名称和正则表达式放入 data class

/* label is the date format and pattern is the regex for that format.
*  result() provides a message (string) when trying to match, but can be
*  modified to get a bool result, like in boolResult(). */
data class DatePatternChecker(val label: String, val pattern: Regex) {
    fun result(dateString: String): String? = if (pattern.matches(dateString)) "Pattern is $label" else null
    fun boolResult(dateString: String): Boolean = pattern.matches(dateString)
    constructor(labelPattern: Map.Entry<String, Regex>) : this(labelPattern.key, labelPattern.value)
}

val datePatternChecks = mapOf(
    "dd/mm/yyyy" to
            "^(3[01]|[12][0-9]|0[1-9]|[1-9])/(1[0-2]|0[1-9]|[1-9])/[0-9]{4}$".toRegex(),
    "mm/dd/yyyy hh:MM:ss" to
            "^(1[0-2]|0[1-9]|[1-9])/(3[01]|[12][0-9]|0[1-9]|[1-9])/[0-9]{4} [0-9][0-9]:([0]?[0-5][0-9]|[0-9]):([0-5][0-9])$".toRegex(),
    // etc.
).map(::DatePatternChecker)

fun String.datePattern(): String = datePatternChecks
    .firstNotNullOfOrNull { it.result(this) }
    ?: "Date pattern not recognized!"

// better
fun String.datePatternByBool(): String = datePatternChecks
    .firstOrNull { it.boolResult(this) }
    ?.run { "Pattern is $label" }
    ?: "Date pattern not recognized!"
// using datePattern
println("21/01/2001".datePattern())           // Pattern is dd/mm/yyyy
println("12/31/2001 13:55:59".datePattern())  // Pattern is mm/dd/yyyy hh:MM:ss
println("99/32/2001".datePattern())           // Date pattern not recognized!
// using datePatternByBool
println("21/01/2001".datePatternByBool())           // Pattern is dd/mm/yyyy
println("12/31/2001 13:55:59".datePatternByBool())  // Pattern is mm/dd/yyyy hh:MM:ss
println("99/32/2001".datePatternByBool())           // Date pattern not recognized!

更实用并且没有重复。如果需要添加新模式或规则,只需将其放入datePatternChecks中正确的position/order;无需其他更改即可使用新模式。