【发布时间】:2021-10-15 22:37:47
【问题描述】:
我试图将一年中的当前日期作为整数在我的程序中访问。我查看了 Kotlin Docs 并找到了一个名为 getDay() 的函数,但是当我将它输入到我的程序中时,它给了我一个错误并说该函数未定义。我正在使用带有 Kotlin 的 Android Studio,最低 API 为 21。
【问题讨论】:
-
听起来你在找人做你的家庭作业...
我试图将一年中的当前日期作为整数在我的程序中访问。我查看了 Kotlin Docs 并找到了一个名为 getDay() 的函数,但是当我将它输入到我的程序中时,它给了我一个错误并说该函数未定义。我正在使用带有 Kotlin 的 Android Studio,最低 API 为 21。
【问题讨论】:
java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*。
使用现代日期时间 API java.time 的解决方案:
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);
}
}
在我的时区输出,欧洲/伦敦:
289
289
从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
java.util.Date 对象仅表示时间轴上的一个瞬间 — 自 UNIX 纪元(格林威治标准时间 1970 年 1 月 1 日 00:00:00)以来的毫秒数的包装。由于它不保存任何时区信息,它的 toString 函数应用 JVM 的时区返回 String,格式为 EEE MMM dd HH:mm:ss zzz yyyy,派生自此 毫秒 值。要以不同的格式和时区获取 java.util.Date 对象的 String 表示,您需要使用具有所需格式和适用时区的 SimpleDateFormat,例如
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);
让我们看看为什么知道上述事实很重要:
函数Calendar#getInstance 返回一个基于默认时区的当前时间的日历,默认为FORMAT 语言环境。如果您想从中找到一些其他时区的信息,您有两种选择:
TimeZone.setDefault(TimeZone.getTimeZone("Australia/Brisbane"))。但是,这可能会导致应用程序的其他部分行为不正确。因此,强烈建议不要使用此选项。SimpleDateFormat 设置格式化java.util.Date(您可以通过Calendar#getTime 获取)并设置上面显示的所需时区。演示:
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();
}
}
发布此答案时我所在时区欧洲/伦敦的输出:
289
289
290
* 如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring。请注意,Android 8.0 Oreo 已经提供了support for java.time。
【讨论】:
Date().getDay() 或者 Kotlin 中的 Date().day 返回星期几,所以不是你想要的。
Calendar.getInstance().get(Calendar.DAY_OF_YEAR) 是在 Android 中使用的正确函数。它使用默认时区和语言环境返回日历。返回的日历基于具有默认 FORMAT 语言环境 (https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--) 的默认时区中的当前时间。
Calendar、Date 等已被 Java 8 的新 java.time 类取代,因此您应该使用 LocalDate.now().dayOfYear,但正如 @nuhkoca 所指出的那样,您需要启用 Java 8+ API 脱糖支持这基本上是将其添加到您的构建文件中(Kotlin DSL 不是 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")
【讨论】:
如果您执行desugaring 以便能够使用Java 8 Time API 返回API 21,则可以使用此方法获取一年中的日期
import java.time.LocalDate
val dayOfYear = LocalDate.now().dayOfYear
System.out.println(dayOfYear);
答案:289
【讨论】:
试试这个代码:
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")
}
【讨论】: