Android使用时区检查打开和关闭时间之间是不是已经过去
Posted
技术标签:
【中文标题】Android使用时区检查打开和关闭时间之间是不是已经过去【英文标题】:Android check if between open and closing time has elapsed using timezoneAndroid使用时区检查打开和关闭时间之间是否已经过去 【发布时间】:2021-10-28 15:30:06 【问题描述】:如何在 android 中检查两次之间的时间? 我有开放时间和关闭时间,我想使用特定的国家时区检查关闭时间是否已经过去。
public void timeElapse(String start, String end, String tz)
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm aa", Locale.getDefault());
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm\\aa", Locale.getDefault());
try
sdf.setTimeZone(tzs);
Date currentTimeDate = sdf.parse(start);
Date endTimeDate = sdf.parse(end);
int a = currentTimeDate.compareTo(endTimeDate); // false / current time has not passed end time.
int b = endTimeDate.compareTo(currentTimeDate); // true / end time has passed current time.
Log.e("timeElapse", "("+end+") A = " + a + " B = " + b);
catch (ParseException ignored)
第二次尝试
public void timeElapse(String start, String end, String tz)
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm\\aa", Locale.getDefault());
try
TimeZone tzs = TimeZone.getTimeZone(tz);
sdf.setTimeZone(tzs);
long currentTimeDate = sdf.parse(start).getTime();
long endTimeDate = sdf.parse(end).getTime();
if(currentTimeDate>endTimeDate)
Log.e("timeElapse", "Time has passed");
else
Log.e("timeElapse", "You are on time");
catch (ParseException ignored)
用法
timeElapse("10:00AM", "10:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "12:00PM", "Asia/Kuala_Lumpur");
timeElapse("11:30AM", "05:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "01:00AM", "Asia/Kuala_Lumpur");
我的代码不起作用。我收到错误 java.text.ParseException: Unparseable date: "10:00AM"
【问题讨论】:
一般情况下,您将时间保存在单个时区(通常为 UTC)中,并将当前时区转换为 UTC 以进行比较。将所有数据保存在一个时区中可以使代码更易于理解,并减少将来出现问题的可能性。 @GabeSechan 你能举个例子吗? 顺便考虑扔掉长期过时且臭名昭著的麻烦SimpleDateFormat
和朋友。看看您是否可以使用desugaring 或将ThreeTenABP 添加到您的Android 项目中,以便使用现代Java 日期和时间API 的java.time。使用起来感觉好多了。
您的尝试是否按预期工作?如果您得到任何意想不到的结果,请为我们说明。
@OleV.V.我的代码不起作用我收到错误java.text.ParseException: Unparseable date: "10:00AM"
【参考方案1】:
java.time 脱糖
考虑使用现代 Java 日期和时间 API java.time 来处理您的时间工作。
在仔细阅读问题后对代码进行了编辑。
private static final DateTimeFormatter TIME_PARSER
= DateTimeFormatter.ofPattern("hh:mma", Locale.ENGLISH);
public static void timeElapse(String start, String end)
LocalTime currentTime = LocalTime.parse(start, TIME_PARSER);
LocalTime endTime = LocalTime.parse(end, TIME_PARSER);
if (currentTime.isAfter(endTime))
System.out.println("Time has passed");
else
System.out.println("You are on time");
代码不是很容易解释吗?这是我觉得 java.time 不错的一件事。并且在 cmets 中已经暗示,我们不需要时区(极端情况除外)。所以我省略了第三个参数。让我们用你的例子来试试吧:
timeElapse("10:00AM", "10:00PM");
timeElapse("10:00AM", "12:00PM");
timeElapse("11:30AM", "05:00PM");
timeElapse("10:00AM", "01:00AM");
输出是:
You are on time You are on time You are on time Time has passed
时区不重要吗?如果您的时间落入回退中,时钟倒转并且相同的时钟小时重复,我们将无法判断哪个更早。我上面的代码没有考虑这种极端情况,为此,我们也需要知道日期。
原码
private static final DateTimeFormatter TIME_PARSER
= DateTimeFormatter.ofPattern("hh:mma", Locale.ENGLISH);
public static void timeElapse(String start, String end, String tz)
LocalTime startTime = LocalTime.parse(start, TIME_PARSER);
LocalTime endTime = LocalTime.parse(end, TIME_PARSER);
LocalTime now = LocalTime.now(ZoneId.of(tz));
if (now.isBefore(startTime))
System.out.println("Not open yet");
else if (now.isAfter(endTime))
System.out.println("Time has passed");
else
System.out.println("You are on time");
代码不是很容易解释吗?这是我觉得 java.time 不错的一件事。让我们用你的例子来试试吧:
timeElapse("10:00AM", "10:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "12:00PM", "Asia/Kuala_Lumpur");
timeElapse("11:30AM", "05:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "01:00AM", "Asia/Kuala_Lumpur");
我在马来西亚凌晨 2 点 15 分左右运行了这段代码,所以正如预期的那样,输出有点枯燥:
Not open yet Not open yet Not open yet Not open yet
我们也试试:
timeElapse("12:00AM", "03:00AM", "Asia/Kuala_Lumpur");
timeElapse("01:00AM", "02:00AM", "Asia/Kuala_Lumpur");
You are on time Time has passed
问题:java.time 不需要 Android API 26 级吗?
java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6。
在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。 在非 Android Java 6 和 7 中,获取 ThreeTen Backport,这是现代类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。 在较旧的 Android 上,请使用脱糖或 Android 版本的 ThreeTen Backport。它被称为 ThreeTenABP。在后一种情况下,请确保从org.threeten.bp
导入日期和时间类以及子包。
你的代码出了什么问题?
您在格式模式字符串中的分钟和 AM/PM 标记之间有一个反斜杠:"hh:mm\\aa"
。这需要在您的时间字符串中使用反斜杠,但它们就像"10:00AM"
,即没有任何反斜杠。我相信这导致了您的ParseException
。为格式化程序指定 Locale.getDefault()
也可能存在问题。 AM 和 PM 在英语以外的其他语言中几乎不使用,但在某些语言中确实有其他名称(文本)。您要求文本使用 JVM(和您的设备)的默认语言。
另外请注意,如果您想将解析的时间与现在的时间进行比较,使用 java.time 很容易。它不适用于Date
和SimpleDateFormat
。 SimpleDateFormat
将每个字符串解析为 1970 年 1 月 1 日的指定时间,因此与现在的时间比较没有意义。
链接
Oracle tutorial: Date Time 解释如何使用 java.time。 Java Specification Request (JSR) 310,其中首次描述了java.time
。
ThreeTen Backport project,java.time
的向后移植到 Java 6 和 7(JSR-310 的 ThreeTen)。
Java 8+ APIs available through desugaring
ThreeTenABP,Android 版 ThreeTen Backport
Question: How to use ThreeTenABP in Android Project,解释得很透彻。
【讨论】:
这很好,但有一点我注意到timeElapse("10:00AM", "05:00AM", "Asia/Kuala_Lumpur")
,当在10AM
附近打开并在5AM
附近关闭时,它总是显示未打开。有什么办法可以查到关门时间是不是隔天?
@Peter 只是有点复杂。参见例如Check if a given time lies between two times regardless of date。如果您需要更多,请搜索更多。以上是关于Android使用时区检查打开和关闭时间之间是不是已经过去的主要内容,如果未能解决你的问题,请参考以下文章