在 Android 上格式化相对于现在的日期的最佳方法
Posted
技术标签:
【中文标题】在 Android 上格式化相对于现在的日期的最佳方法【英文标题】:Best way to format a date relative to now on Android 【发布时间】:2013-01-19 04:53:29 【问题描述】:我正在 android 应用程序中创建一个功能,以获取任意日期(过去、现在或未来)并找到与现在相关的差异。
我的now
和due
变量都是longs
,这是我的代码:
long now = System.currentTimeMillis();
long due = now + 864000;
Log.d("Time in 1 day", DateUtils.getRelativeTimeSpanString(due,now, DateUtils.DAY_IN_MILLIS));
我希望输出类似于 yesterday
、today
、in 4 days
或 19/12/2012
。但是,当前输出返回in 0 days
...
我不希望时间出现在这些日期字符串上。
我做错了什么,是在 Android 上格式化日期的最佳方法吗?
【问题讨论】:
【参考方案1】:我的想法正在改变:
DateUtils.getRelativeTimeSpanString(due, now, 0L, DateUtils.FORMAT_ABBREV_ALL);
由于文档说它返回相对于现在的时间。
如果失败,请使用一些出色的库:
Joda Time
PrettyTime
TimeAgo
【讨论】:
如果我需要几天后的差异,这将不起作用!例如。 “14 天前”而不是“2 周前” @oleynikd 使用 DateUtils.DAY_IN_MILLIS 而不是 0L【参考方案2】:我终于实现了你想要的..!
首先你需要下载Joda Time from here
解压到任意文件夹,将joda-time-2.2.jar放入androidProject/libs文件夹。
MainActivity
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.MutableDateTime;
import org.joda.time.Weeks;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends Activity
private int day ;
private int month ;
private int year ;
private int hour ;
private int minute ;
private long selectedTimeInMillis;
private long currentTimeInMillis;
private String strDay ="";
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
year = 2013;
month = 8;
day = 10;
hour = 15;
minute = 28;
DateTime selectedTime = new DateTime(year,month,day,hour,minute);
selectedTimeInMillis = selectedTime.getMillis();
MutableDateTime epoch = new MutableDateTime();
epoch.setDate(selectedTimeInMillis); //Set to Epoch time
DateTime now = new DateTime();
currentTimeInMillis = now.getMillis();
int days = Days.daysBetween(epoch, now).getDays();
int weeks = Weeks.weeksBetween(epoch, now).getWeeks();
int months = Months.monthsBetween(epoch, now).getMonths();
Log.v("days since epoch: ",""+days);
Log.v("weeks since epoch: ",""+weeks);
Log.v("months since epoch: ",""+months);
if(selectedTimeInMillis < currentTimeInMillis) //Past
long yesterdayTimeInMillis = currentTimeInMillis - 86400000;
DateTime today = new DateTime(currentTimeInMillis);
int year = today.getDayOfYear();
int intToday = today.getDayOfMonth();
DateTime yesterday = new DateTime(yesterdayTimeInMillis);
int intYesterday = yesterday.getDayOfMonth();
DateTime selectedDay = new DateTime(selectedTimeInMillis);
int intselectedDay = selectedDay.getDayOfMonth();
int intselectedYear = selectedDay.getDayOfYear();
if(intToday == intselectedDay & year == intselectedYear)
strDay = "today";
else if(intYesterday == intselectedDay)
strDay = "yesterday";
else
strDay = "before "+ days +" days from today";
else if(selectedTimeInMillis > currentTimeInMillis) //Future
long tomorrowTimeInMillis = currentTimeInMillis + 86400000;
DateTime tomorrow = new DateTime(tomorrowTimeInMillis);
int intTomorrow = tomorrow.getDayOfMonth();
DateTime today = new DateTime(selectedTimeInMillis);
int intToday = today.getDayOfMonth();
if(intToday == intTomorrow)
strDay = "tomorrow";
else
days = -days;
strDay = "after "+ days +" days from today";
Log.v("strDay: ",""+strDay);
你只需要改变 day 的值,你就会得到期望的输出。 目前我已将日期 10 作为输入,因此输出将是今天。
我设置了 date/day = 10 , month = 8 , year = 2013 , hour = 15 , min = 28
对于过去的日期:
input day 9 output yesterday
input day 3 output before 7 days from today
input year 2012 and day 10 output before 365 days from today
未来日期:
input day 11 output tomorrow
input day 27 output after 17 days from today
input day 23 and year 2016 output after 1109 days from today
【讨论】:
Prettytime lib 也是非常人类可读的时间格式londatiga.net/it/programming/android/… @Lorensius W. L. T 谢谢。我会测试一下。 哦,我一直在寻找这个,现在我测试了这种方法,并且像魅力一样工作!谢谢大佬 如何从这种方法中获得小时和分钟的差异?我们可以得到过去/未来的小时、分钟等吗? @naveed ahmad 是的,伙计,你可以从毫秒中提取小时和分钟......而且你可以得到差异......:)【参考方案3】:为什么不只检查yesterday
和tomorrow
以避免in 0 days
/0 days ago
错误并让DateUtils.getRelativeTimeSpanString
处理其余情况?
String relative = null;
if(now < due && (due-now)<864000)
relative = "tomorrow";
else if(now > due && (now-due)<864000)
relative = "yesterday";
else
relative = DateUtils.getRelativeTimeSpanString(due, now, DateUtils.DAY_IN_MILLIS); // e.g. "in 4 days"
Log.d("result", relative);
编辑:您也可以通过简单的检查添加today
。
【讨论】:
如果时间超过几周前,这似乎无法正常工作。该函数返回月份和日期(例如 2 月 2 日)。 这不适应本地化,仅供参考。【参考方案4】:在 Android 上格式化相对于现在的日期的最佳方式
我建议你使用JodaTime
它是轻量级方便的库,我认为实际上是处理 Date 实例的最佳工具。
你可以开始here。
【讨论】:
一个 500kb 的库,用于这样简单的事情?除非我的应用真的依赖于日期(例如日历应用),否则我会坚持使用嵌入在操作系统中的DateUtils
。
@WordPressDeveloper JodaTime 实际上是最好的,但我尊重你的意见。
我同意@hasMobi-AndroidApps 没有“最佳”库之类的东西。一切都是为了权衡。【参考方案5】:
build.gradle
compile 'joda-time:joda-time:2.9.9'
Utils.java
private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd, yyyy");
private static SimpleDateFormat TIME_FORMAT = new SimpleDateFormat(" 'at' h:mm aa");
public static String getRelativeDateTimeString(Calendar startDateCalendar)
if (startDateCalendar == null) return null;
DateTime startDate = new DateTime(startDateCalendar.getTimeInMillis());
DateTime today = new DateTime();
int days = Days.daysBetween(today.withTimeAtStartOfDay(), startDate.withTimeAtStartOfDay()).getDays();
String date;
switch (days)
case -1: date = "Yesterday"; break;
case 0: date = "Today"; break;
case 1: date = "Tomorrow"; break;
default: date = DATE_FORMAT.format(startDateCalendar.getTime()); break;
String time = TIME_FORMAT.format(startDateCalendar.getTime());
return date + time;
输出
Yesterday at 9:52 AM
Today at 9:52 AM
Tomorrow at 9:52 AM
Sep 05, 2017 at 9:52 AM
【讨论】:
【参考方案6】:实际原因是数字 864000 以毫秒为单位,对应 14 分钟。与 DAY_IN_MILLIS(一天)相比,14 分钟太小了。在那里你得到“0天”。 如果您希望它“在 14 分钟内”产生,只需将 DAY_IN_MILLIS 更改为 MIN_IN_MILLIS。
【讨论】:
我想得到“今天”!不是“0 天内”或“14 分钟内”【参考方案7】:我来这里是为了另一种选择,但我找不到完美的代码,而不是我的代码。 所以我在这里分享了任何改进。
public String getCreatedAtRelative()
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
df.setTimeZone(TimeZone.getTimeZone("IST"));
CharSequence relative = null;
try
relative = DateUtils.getRelativeTimeSpanString(df.parse(createdAt).getTime(), new Date().getTime(),
0L, DateUtils.FORMAT_ABBREV_ALL);
catch (ParseException e)
Log.e("Parse Exception adapter", "created at", e);
catch (NullPointerException e)
e.printStackTrace();
if (null == relative)
return createdAt;
else
return relative.toString().replace(".", " ");
【讨论】:
【参考方案8】:所以你的计算是以毫秒为单位的,然后你用 SimpleDateFormat 格式化结果。
为此,您可以像这样轻松使用 SimpleDateFormat 格式化程序:
Date date = new Date(milliseconds);
SimpleDateFormat formatter = new SimpleDateFormat("EEEE dd MMMM yyyy");
String strDate = formatter.format(date);
所以你的计算应该以毫秒为单位,然后你用 SimpleDateFormat 格式化结果。
模式(“EEEE dd MMMM yyyy”)允许您获取日期格式,例如 2013 年 2 月 4 日星期一。
您可以随意更改模式:“EEEE dd/MM/yy”,...
【讨论】:
那不会给我relative日期吧?我想要today
和in two days
之类的日期【参考方案9】:
对于Android,您可以使用Joda-Time-Android 库的最简单方法:
Date yourTime = new Date();
DateTime dateTime = new DateTime(yourTime); //or simple DateTime.now()
final String result = DateUtils.getRelativeTimeSpanString(getContext(), dateTime);
【讨论】:
TinTran 的例子?【参考方案10】:long now = System.currentTimeMillis();
DateUtils.getRelativeDateTimeString(mContext, now), DateUtils.SECOND_IN_MILLIS, DateUtils.DAY_IN_MILLIS, 0)
a link!
【讨论】:
以上是关于在 Android 上格式化相对于现在的日期的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
在 Android SQLite 中处理日期的最佳方式 [关闭]
Jquery Datatable - 日期排序不适用于月份(相对于日期的月份)
适用于 PC 的最佳 Android 操作系统(2022 版)