-1

I need to get the date today, and the date one month ago in the format yyyy-mm-dd

To get the date today i have:

val todaysDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()).toString()

Which works as i want:

2021-05-12

However i cannot figure out how to get the date for one month ago in the same format. I found this function in another thread but it returns "Mon Apr 12 18:24:37 GMT+02:00 2021"

    fun getDaysAgo(daysAgo: Int): Date {
        val calendar = Calendar.getInstance()
        calendar.add(Calendar.DAY_OF_YEAR, -daysAgo)

        return calendar.time
    }

How can i get the date one month ago in the same format? Thanks.

Edit:

The solution for me was actually very simple using the getDaysAgo function

var daysAgo= SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(getDaysAgo(30)).toString()

However Ole's answer below is probably better and the recommended way. Did not work for me as it requires api level 26 (android) and im on 23.

Jamshed
  • 159
  • 1
  • 7
  • 1
    LocalDate.now().minusMonths(1) – Michael May 12 '21 at 16:35
  • Why format the date before you do the date math? Or after you have the new date from `getDaysAgo` why not format *that* date? (With the caveat about `minusMonths` existing as indicated in the first comment.) – Dave Newton May 12 '21 at 16:36
  • 2
    Worth bearing in mind, what if the date is say May 31st? There is no Feb 31st. 1 month is not a well-defined duration of time. Months are different lengths. `java.time` classes will push back the day until the first valid day in that month. For Feb, either 28th or 29th depending on whether it's a leap year. – Michael May 12 '21 at 16:37
  • 1
    Use java.time types instead of Calendar, Date, or SimpleDateFormat. – Louis Wasserman May 12 '21 at 16:41
  • The `getDaysAgo()` function you have here returns a `Date`, not a formatted string, so you can't really say that the format is not what you want. You can format *that* date just like you did for `Date()` when you wanted today's date. However, as others said in the comments, you'd better use `java.time` APIs instead. – Joffrey May 12 '21 at 16:43
  • @Joffrey How can i format `Date` to "yyy-mm-dd"? Does not work with SimpleDateFormat as it requires locale. Aka How do i get from "Mon Apr 12 19:24:03 GMT+02:00 2021" to "2021-04-12" – Jamshed May 12 '21 at 17:29
  • @Jamshed you actually did format a `Date` object in your first example line for today, so if this works you can just replace `Date()` by whatever return value you got from `getDaysAgo()`. – Joffrey May 12 '21 at 18:53
  • 1
    As Louis Wasserman already mentioned, you should **stop immediately** using `Date`, `Calendar` and `SimpleDateFormat`. They have been obsolete for a long time now. And [they are troublesome](https://stackoverflow.com/questions/1969442/whats-wrong-with-java-date-time-api). Use classes from the [`java.time`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/time/package-summary.html) package instead. – MC Emperor May 12 '21 at 18:57
  • You are really asking two questions in one. Please see if you can separate them in your head. (1) How to get the date 1 month ago? (2) How to format the date I got from (1) into yyyy-mm-dd format (also known as [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format)? – Ole V.V. May 12 '21 at 20:30

1 Answers1

2

LocalDate from java.time

  1. Keep and process dates as LocalDate objects, not as strings.
  2. Only when you need to give string output, format your LocalDate into a string in the appropriate format.

Like many in the comments I recommend that you use java.time, the modern Java date and time API, for your date work. In Java code, still keeping processing and formatting separate and trusting you to translate to Kotlin yourself:

public static LocalDate get1MonthAgo() {
    return LocalDate.now(ZoneId.systemDefault()).minusMonths(1);
}

public static String formatToIso8601(LocalDate date) {
    return date.toString();
}

Assuming that you need to output the date 1 month ago as a string, use the two methods like this:

    LocalDate oneMonthAgo = get1MonthAgo();

    String oneMonthAgoFormatted = formatToIso8601(oneMonthAgo);
    System.out.println(oneMonthAgoFormatted);

When I ran this evening in my time zone, the output was:

2021-04-12

I am exploiting the facts that the format you asked for is ISO 8601, the international format, and that LocalDate (and also the other date-time classes of java.time) produce(s) ISO 8601 format from their toString methods. So we need to specify no formatter. Which is good because fiddling with a format pattern string is always error-prone.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161