get the day of the year as an integer in Kotlin Android Studio

Viewed 1390

I am trying to get the current day of the year as an integer to access within my program. I looked at the Kotlin Docs and found a function called getDay(), but when I type it into my program it gives me an error and says the function is not defined. I am using Android Studio with Kotlin and the minimum API is 21.

IDE code Error

4 Answers

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Note: If you want to work with a specific timezone, use LocalDate.now(ZoneId)
        // e.g. LocalDate.now(ZoneId.of("Australia/Brisbane")) or
        // LocalDate.now(ZoneOffset.UTC) etc.
        LocalDate today = LocalDate.now();

        int doy = today.getDayOfYear();
        System.out.println(doy);

        // Using DateTimeFormatter (not recommended for production code)
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("D", Locale.ENGLISH);
        String strDoy = today.format(dtf);
        System.out.println(strDoy);
    }
}

Output in my timezone, Europe/London:

289
289

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

For any reason, if you want to use the legacy API:

A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.

Date date = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);

sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);

sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);

Let's see why knowing the above fact is important:

The function, Calendar#getInstance returns a calendar based on the current time in the default time zone with the default FORMAT locale. If you want to find some information from it for some other timezone, you have two options:

  1. Change the default timezone e.g. TimeZone.setDefault(TimeZone.getTimeZone("Australia/Brisbane")). However, this may result in other parts of the application behave incorrectly. Therefore, this option is strongly discouraged.
  2. Format the java.util.Date (which you can get via Calendar#getTime) using SimpleDateFormat set with the required timezone shown above.

Demo:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Date now = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("D");

        // For the JVM's timezone
        sdf.setTimeZone(TimeZone.getDefault());
        System.out.println(sdf.format(now));

        // For the timezone, UTC
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println(sdf.format(now));

        // For the timezone, Australia/Brisbane
        sdf.setTimeZone(TimeZone.getTimeZone("Australia/Brisbane"));
        System.out.println(sdf.format(now));

        System.out.println();
    }
}

Output in my timezone, Europe/London at the time of posting this answer:

289
289
290

ONLINE DEMO


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time.

If you perform desugaring in order to be able to use Java 8 Time API back to API 21, you can then use this method to get the day of year

import java.time.LocalDate

val dayOfYear = LocalDate.now().dayOfYear
System.out.println(dayOfYear);

Answer: 289

Date().getDay() or rather Date().day in Kotlin returns the day of the week so not what you want.

Calendar.getInstance().get(Calendar.DAY_OF_YEAR) is the correct function to use in Android. It returns a calendar using the default time zone and locale. The Calendar returned is based on the current time in the default time zone with the default FORMAT locale (https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--).

Calendar, Date etc. have been replaced by new java.time classes with Java 8 so you should use LocalDate.now().dayOfYear but as @nuhkoca indicates in order to do that you need to enable Java 8+ API desugaring support which is basically adding this to your build file (Kotlin DSL not Groovy):

compileOptions {
   isCoreLibraryDesugaringEnabled = true
   sourceCompatibility = JavaVersion.VERSION_1_8
   targetCompatibility = JavaVersion.VERSION_1_8
}

kotlinOptions {
   jvmTarget = "1.8"
}

dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")

try this code :

import java.time.LocalDate
import java.util.*




fun main() {

    val cal = Calendar.getInstance()
    val day = cal[Calendar.DATE]
    val doy = cal[Calendar.DAY_OF_YEAR]

    println("Current Date: " + cal.time)
    println("Day         : $day")

    println("Day of Year : $doy")
}
Related