Created
March 16, 2021 15:23
-
-
Save esabook/51477179a995ea935149d15035b1f5a8 to your computer and use it in GitHub Desktop.
[Kotlin-JVM] Custom monthNames, relativeDate, stringToDate, DateToString
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package * | |
import android.text.format.DateUtils | |
import java.text.SimpleDateFormat | |
import java.util.* | |
import java.util.concurrent.TimeUnit.MILLISECONDS | |
import kotlin.math.abs | |
object DateFormatUtils { | |
val DEFAULT_FROM_DATE_PATTERN = "yyyy-MM-dd" | |
val DEFAULT_FROM_DATE_PATTERN_LONG = "yyyy-MM-dd HH:mm:ss" | |
val DEFAULT_TO_DATE_PATTERN = "yyyy MMM dd" | |
val longMonthNamesIndo = arrayOf( | |
"Januari", | |
"Februari", | |
"Maret", | |
"April", | |
"Mei", | |
"Juni", | |
"Juli", | |
"Agustus", | |
"September", | |
"Oktober", | |
"November", | |
"Desember" | |
) | |
val shortMonthNamesIndo = arrayOf( | |
"Jan", | |
"Feb", | |
"Mar", | |
"Apr", | |
"Mei", | |
"Jun", | |
"Jul", | |
"Agu", | |
"Sep", | |
"Okt", | |
"Nov", | |
"Des" | |
) | |
/** | |
* | |
*/ | |
fun String.localizeDate(fromPatter: String = DEFAULT_FROM_DATE_PATTERN, toPattern: String = DEFAULT_TO_DATE_PATTERN): String { | |
return try { | |
val sdf = SimpleDateFormat(toPattern, Locale.getDefault()) | |
val dfs = sdf.dateFormatSymbols | |
dfs.months = longMonthNamesIndo | |
dfs.shortMonths = shortMonthNamesIndo | |
sdf.dateFormatSymbols = dfs | |
val date = this.toDateOrNull(fromPatter) | |
return sdf.format(date) | |
} catch (ignored: Exception) { | |
this | |
} | |
} | |
fun String?.localizeDate(targetPattern: String, vararg fromPattern: String): String? { | |
return this?.toDateOrNull(*fromPattern) | |
.takeIf { it != null } | |
?.toString(targetPattern, true) | |
?: this | |
} | |
/** | |
* 1. dibawah 1 jam, tampilin menit (contoh: 59 menit yang lalu) | |
* 2. dibawah <24 jam, tampilin per jam (contoh 2 jam yang lalu). Kalau 1 jam 29 menit itu 1 jam, 1 jam 30 menit itu 2 jam | |
* 3. dibawah 1 minggu, hari (contoh kemarin, 2 hari yang lalu, 5 hari yang lalu) | |
* 4. diatas 1 minggu, tanggal (contoh 11 Mei) | |
* 5. beda tahun, DD MMM YYYY (contoh 11 Mei 2020) | |
*/ | |
fun Date.relativeLocalizeDate(): String { | |
val milliseconds = time - System.currentTimeMillis() | |
val positiveValue = abs(milliseconds) | |
val now = Date().time | |
val prePostSuffix = if (time > now) "lagi" else "yang lalu" | |
return when { | |
this.year != Date().year -> toString("dd MMM yyyy", true) | |
positiveValue > DateUtils.WEEK_IN_MILLIS -> toString("dd MMM", true) | |
positiveValue > DateUtils.DAY_IN_MILLIS -> "${MILLISECONDS.toDays(positiveValue)} hari $prePostSuffix" | |
positiveValue > DateUtils.HOUR_IN_MILLIS -> "${abs((MILLISECONDS.toMinutes(positiveValue) / 90).toInt()) + 1} jam $prePostSuffix" | |
positiveValue > DateUtils.MINUTE_IN_MILLIS -> "${MILLISECONDS.toMinutes(positiveValue)} menit $prePostSuffix" | |
else -> "Baru saja" | |
} | |
} | |
/** | |
* we have nonStandard format if 10:30:30+07:00 from hh:mm:ssXXX | |
* should read as 03:30:30 | |
* | |
* Example: | |
* ``` | |
* val publishAtDateFormat = arrayOf( | |
* "yyyy-MM-dd HH:mm:ss", | |
* "yyyy-MM-dd'T'HH:mm:ss.SS'Z'", | |
* "yyyy-MM-dd'T'HH:mm:ssXXX", | |
* "yyyy-MM-dd'T'HH:mm:ss'Z'", | |
* "yyyy-MM-dd'T'HH:mm:ss.SSSZ", | |
* "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", | |
* "yyyy-MM-dd'T'HH:mm:ss:SS'Z'") | |
* | |
* dateInString.toDateOrNull(*publishAtDateFormat) | |
* ``` | |
*/ | |
fun String.toDateOrNull(vararg pattern: String, minusGMT: Boolean = false): Date? { | |
if (this.isEmpty()) return null | |
pattern.asList().forEach { | |
try { | |
return SimpleDateFormat(it, Locale.getDefault()).parse(this)?.apply { | |
if (!minusGMT) return@apply | |
val calendar = Calendar.getInstance() | |
calendar.time = this | |
time -= calendar.get(Calendar.ZONE_OFFSET) | |
} | |
} catch (ignored: Exception) { | |
} | |
} | |
return null | |
} | |
/** | |
* Example: | |
* ```publishDate.toString("dd MMM yyyy", true)``` | |
*/ | |
fun Date.toString(pattern: String, isLocalized: Boolean = false): String { | |
return try { | |
if (isLocalized) | |
toString(DEFAULT_FROM_DATE_PATTERN_LONG).localizeDate(DEFAULT_FROM_DATE_PATTERN_LONG, pattern) | |
else | |
SimpleDateFormat(pattern, Locale.getDefault()).format(this) | |
} catch (ignored: Exception) { | |
this.toString() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment