From 5795183ca6e185147d7751e6407917cf0fb7a522 Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Wed, 16 Mar 2022 13:38:34 +0100 Subject: [PATCH] feat: relative date treatment and bg --- .../fragments/TreatmentsBolusCarbsFragment.kt | 11 ++-- .../fragments/TreatmentsCareportalFragment.kt | 10 ++-- .../TreatmentsExtendedBolusesFragment.kt | 12 ++-- .../TreatmentsProfileSwitchFragment.kt | 8 +-- .../fragments/TreatmentsTempTargetFragment.kt | 10 ++-- .../TreatmentsTemporaryBasalsFragment.kt | 9 +-- .../fragments/TreatmentsUserEntryFragment.kt | 8 +-- .../plugins/source/BGSourceFragment.kt | 6 +- .../nightscout/androidaps/utils/DateUtil.kt | 58 ++++++++++++++++++- core/src/main/res/values/strings.xml | 8 +++ 10 files changed, 100 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt index 1c569a78a6..c4a23113bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -3,7 +3,6 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint import android.graphics.Paint import android.os.Bundle -import android.util.Log import android.util.SparseArray import android.view.* import android.widget.CompoundButton @@ -190,7 +189,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - removeActionMode?.let { it.finish() } + removeActionMode?.finish() binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -206,9 +205,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { val profile = profileFunction.getProfile() ?: return val ml = mealLinks[position] - val sameDayPrevious = position > 0 && dateUtil.isSameDay(timestamp(ml), timestamp(mealLinks[position - 1])) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(timestamp(ml)) + val newDay = position == 0 || !dateUtil.isSameDayGroup(timestamp(ml), timestamp(mealLinks[position - 1])) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(timestamp(ml), rh) else "" // Metadata holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility() @@ -272,7 +271,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } holder.binding.calculation.tag = ml val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(timestamp(ml), nextTimestamp).toVisibility() } override fun getItemCount() = mealLinks.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt index 6e0bfcf4a7..0f7fb29725 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt @@ -149,7 +149,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - removeActionMode?.let { it.finish() } + removeActionMode?.finish() binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -165,9 +165,9 @@ class TreatmentsCareportalFragment : DaggerFragment() { val therapyEvent = therapyList[position] holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(therapyEvent.timestamp, therapyList[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(therapyEvent.timestamp) + val newDay = position == 0 || !dateUtil.isSameDayGroup(therapyEvent.timestamp, therapyList[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(therapyEvent.timestamp, rh) else "" holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp) holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh) holder.binding.note.text = therapyEvent.note @@ -185,7 +185,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(therapyEvent.timestamp, nextTimestamp).toVisibility() } override fun getItemCount() = therapyList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt index e1d8d4b34d..a9ccda548c 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt @@ -1,6 +1,5 @@ package info.nightscout.androidaps.activities.fragments -import android.annotation.SuppressLint import android.os.Bundle import android.util.SparseArray import android.view.* @@ -114,7 +113,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - removeActionMode?.let { it.finish() } + removeActionMode?.finish() binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -131,10 +130,9 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp) - @SuppressLint("SetTextI18n") + val newDay = position == 0 || !dateUtil.isSameDayGroup(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(extendedBolus.timestamp, rh) else "" if (extendedBolus.isInProgress(dateUtil)) { holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp) holder.binding.time.setTextColor(rh.gc(R.color.colorActive)) @@ -162,7 +160,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(extendedBolus.timestamp, nextTimestamp).toVisibility() } override fun getItemCount() = extendedBolusList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt index 08d4e20240..7fa2063e64 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt @@ -184,9 +184,9 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { val profileSwitch = profileSwitchList[position] holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility() holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp) + val newDay = position == 0 || !dateUtil.isSameDayGroup(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(profileSwitch.timestamp, rh) else "" holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp) holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins()) holder.binding.name.text = @@ -213,7 +213,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(profileSwitch.timestamp, nextTimestamp).toVisibility() } override fun getItemCount() = profileSwitchList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt index 777a61a932..f022fae27d 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt @@ -154,7 +154,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - removeActionMode?.let { it.finish() } + removeActionMode?.finish() binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -185,9 +185,9 @@ class TreatmentsTempTargetFragment : DaggerFragment() { } holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } - val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp) + val newDay = position == 0 || !dateUtil.isSameDayGroup(tempTarget.timestamp, tempTargetList[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempTarget.timestamp, rh) else "" holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end) holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins()) holder.binding.low.text = tempTarget.lowValueToUnitsToString(units) @@ -201,7 +201,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { } ) val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempTarget.timestamp, nextTimestamp).toVisibility() } override fun getItemCount() = tempTargetList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt index d5538f3a41..b1ac871b5a 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -1,7 +1,6 @@ package info.nightscout.androidaps.activities.fragments import android.os.Bundle -import android.util.Log import android.util.SparseArray import android.view.* import androidx.appcompat.widget.Toolbar @@ -155,7 +154,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - removeActionMode?.let { it.finish() } + removeActionMode?.finish() binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -172,7 +171,9 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility() val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp) + val newDay = position == 0 || !dateUtil.isSameDayGroup(tempBasal.timestamp, tempBasalList[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempBasal.timestamp, rh) else "" if (tempBasal.isInProgress) { holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp) holder.binding.time.setTextColor(rh.gc(R.color.colorActive)) @@ -206,7 +207,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempBasal.timestamp, nextTimestamp).toVisibility() } override fun getItemCount() = tempBasalList.size diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt index ac8c3b68e1..71cb5c1084 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt @@ -128,9 +128,9 @@ class TreatmentsUserEntryFragment : DaggerFragment() { override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) { val current = entries[position] - val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(current.timestamp) + val newDay = position == 0 || !dateUtil.isSameDayGroup(current.timestamp, entries[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(current.timestamp, rh) else "" holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp) holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action) holder.binding.notes.text = current.note @@ -140,7 +140,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() { holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values) holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L - holder.binding.delimiter.visibility = dateUtil.isSameDay(current.timestamp, nextTimestamp).toVisibility() + holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(current.timestamp, nextTimestamp).toVisibility() } inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index c56b34c032..e175939d4c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -147,9 +147,9 @@ class BGSourceFragment : DaggerFragment() { val glucoseValue = glucoseValues[position] holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp) - holder.binding.date.visibility = sameDayPrevious.not().toVisibility() - holder.binding.date.text = dateUtil.dateString(glucoseValue.timestamp) + val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp) + holder.binding.date.visibility = newDay.toVisibility() + holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else "" holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp) holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt index a8c8f504fd..6b6f79f493 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/DateUtil.kt @@ -24,6 +24,8 @@ import java.util.stream.Collectors import javax.inject.Inject import javax.inject.Singleton import kotlin.math.abs +import kotlin.math.ceil +import kotlin.math.floor /** * The Class DateUtil. A simple wrapper around SimpleDateFormat to ease the handling of iso date string <-> date obj @@ -56,8 +58,6 @@ class DateUtil @Inject constructor(private val context: Context) { * Render date * * @param date the date obj - * @param format - if not specified, will use FORMAT_DATE_ISO - * @param tz - tz to set to, if not specified uses local timezone * @return the iso-formatted date string */ fun toISOString(date: Long): String { @@ -104,6 +104,26 @@ class DateUtil @Inject constructor(private val context: Context) { return df.format(mills) } + fun dateStringRelative(mills: Long, rh: ResourceHelper): String { + val df = DateFormat.getDateInstance(DateFormat.SHORT) + val day = df.format(mills) + val beginOfToday = beginOfDay(now()) + return if (mills < now()) // Past + when { + mills > beginOfToday -> rh.gs(R.string.today) + mills > beginOfToday - T.days(1).msecs() -> rh.gs(R.string.yesterday) + mills > beginOfToday - T.days(7).msecs() -> dayAgo(mills, rh, true) + else -> day + } + else // Future + when { + mills < beginOfToday + T.days(1).msecs() -> rh.gs(R.string.later_today) + mills < beginOfToday + T.days(2).msecs() -> rh.gs(R.string.tomorrow) + mills < beginOfToday + T.days(7).msecs() -> dayAgo(mills, rh, true) + else -> day + } + } + fun dateStringShort(mills: Long): String { var format = "MM/dd" if (android.text.format.DateFormat.is24HourFormat(context)) { @@ -167,6 +187,33 @@ class DateUtil @Inject constructor(private val context: Context) { return rh.gs(R.string.hoursago, hours) } + fun dayAgo(time: Long, rh: ResourceHelper, round: Boolean = false): String { + var days = (now() - time) / 1000.0 / 60 / 60 / 24 + if (round) { + if (now() > time) { + days = ceil(days) + return rh.gs(R.string.days_ago_round, days) + } else { + days = floor(days) + return rh.gs(R.string.in_days_round, days) + } + } + return if (now() > time) + rh.gs(R.string.days_ago, days) + else + rh.gs(R.string.in_days, days) + } + + fun beginOfDay(mills: Long): Long { + val givenDate = Calendar.getInstance() + givenDate.timeInMillis = mills + givenDate[Calendar.HOUR_OF_DAY] = 0 + givenDate[Calendar.MINUTE] = 0 + givenDate[Calendar.SECOND] = 0 + givenDate[Calendar.MILLISECOND] = 0 + return givenDate.timeInMillis + } + fun timeStringFromSeconds(seconds: Int): String { val cached = timeStrings[seconds.toLong()] if (cached != null) return cached @@ -220,6 +267,13 @@ class DateUtil @Inject constructor(private val context: Context) { fun isSameDay(timestamp1: Long, timestamp2: Long) = isSameDay(Date(timestamp1), Date(timestamp2)) + fun isSameDayGroup(timestamp1: Long, timestamp2: Long): Boolean { + val now = now() + if (timestamp1 < now && timestamp2 > now || timestamp1 > now && timestamp2 < now) + return false + return isSameDay(Date(timestamp1), Date(timestamp2)) + } + //Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} fun computeDiff(date1: Long, date2: Long): Map { val units: MutableList = ArrayList(EnumSet.allOf(TimeUnit::class.java)) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 65ad75af76..aa90c26865 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -204,6 +204,10 @@ %1$d m ago %1$d minutes ago %1$.1f h ago + %1$.1f days ago + %1$.0f days ago + in %1$.0f days + in %1$.0f days h days hours @@ -219,6 +223,10 @@ weeks m d + Later today + Tomorrow + Today + Yesterday Wrong password