在 Android 上格式化相对于现在的日期的最佳方法

Posted

技术标签:

【中文标题】在 Android 上格式化相对于现在的日期的最佳方法【英文标题】:Best way to format a date relative to now on Android 【发布时间】:2013-01-19 04:53:29 【问题描述】:

我正在 android 应用程序中创建一个功能,以获取任意日期(过去、现在或未来)并找到与现在相关的差异。

我的nowdue 变量都是longs,这是我的代码:

long now = System.currentTimeMillis();
long due = now + 864000;

Log.d("Time in 1 day", DateUtils.getRelativeTimeSpanString(due,now, DateUtils.DAY_IN_MILLIS));

我希望输出类似于 yesterdaytodayin 4 days19/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】:

为什么不只检查yesterdaytomorrow 以避免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日期吧?我想要todayin 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 中处理日期的最佳方式 [关闭]

Android 读写锁的应用,以及最佳的磁盘缓存设计

Jquery Datatable - 日期排序不适用于月份(相对于日期的月份)

适用于 PC 的最佳 Android 操作系统(2022 版)

在android中跟踪相对于LinearLayout的滚动tableRows

适用于 BigQuery 的最佳 Google Cloud Storage