有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Momentjs calendar()等效于Java

Momentjs具有calendar()函数,可以很好地打印时间跨度,如下所示

例如:

"Last Monday at 1:14 PM"

"09/21/2017" (if the date is a while ago)

Java中是否有等价的函数(如果可能的话是Joda Time)

moment().subtract(10, 'days').calendar(); // 09/21/2017
moment().subtract(6, 'days').calendar();  // Last Monday at 1:14 PM
moment().subtract(3, 'days').calendar();  // Last Thursday at 1:14 PM
moment().subtract(1, 'days').calendar();  // Yesterday at 1:14 PM
moment().calendar();                      // Today at 1:14 PM
moment().add(1, 'days').calendar();       // Tomorrow at 1:14 PM
moment().add(3, 'days').calendar();       // Wednesday at 1:14 PM
moment().add(10, 'days').calendar();      // 10/11/2017

共 (2) 个答案

  1. # 1 楼答案

    Java中没有内置函数,但使用现有的API并不难。首先,您需要获得今天的差异(以天为单位),并根据moment.js rules选择合适的字符串:

    Last week         Last Monday at 2:30 AM
    The day before    Yesterday at 2:30 AM
    The same day      Today at 2:30 AM
    The next day      Tomorrow at 2:30 AM
    The next week     Sunday at 2:30 AM
    Everything else   7/10/2011
    

    在Joda Time中,您可以使用org.joda.time.Days类以天为单位计算差值。一个细节是,我只考虑日期(天/月/年),而忽略了获得差异的时间(小时/分钟/秒)(但你可以根据自己的需要进行调整)。方法如下:

    public String calendar(DateTime dt) {
        StringBuilder sb = new StringBuilder();
    
        // check difference in days from today, considering just the date (ignoring the hours)
        int days = Days.daysBetween(new LocalDate(), dt.toLocalDate()).getDays();
        if (days == 0) { // today
            sb.append("Today ");
        } else if (days == 1) { // tomorrow
            sb.append("Tomorrow ");
        } else if (days == -1) { // yesterday
            sb.append("Yesterday ");
        } else if (days > 0 && days < 7) { // next week
            sb.append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
        } else if (days < 0 && days > -7) { // last week
            sb.append("Last ").append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
        }
    
        if (Math.abs(days) < 7) { // difference is less than a week, append current time
            sb.append("at ").append(dt.toString("h:mm a", Locale.ENGLISH));
        } else { // more than a week of difference
            sb.append(dt.toString("M/d/yyyy"));
        }
    
        return sb.toString();
    }
    

    我使用org.joda.time.LocalDate来获得差异,因此时间将被忽略(如果使用DateTime,如果超过24小时,差异仅为1天,因此根据需要更改代码)

    我也使用^ {CD4>}来考虑差异是否超过一个星期,但我不确定^ {< CD5>}是否考虑^ {CD6>}。

    总之,下面是一些用法示例:

    DateTime now = new DateTime();
    System.out.println(calendar(now.minusDays(10))); // 9/22/2017
    System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
    System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
    System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
    System.out.println(calendar(now)); // Today at 9:34 AM
    System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
    System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
    System.out.println(calendar(now.plusDays(10))); // 10/12/2017
    

    输出是(考虑到今天是2017年10月2日,我在当地时间上午9:34运行了代码):

    9/22/2017
    Last Tuesday at 9:34 AM
    Last Friday at 9:34 AM
    Yesterday at 9:34 AM
    Today at 9:34 AM
    Tomorrow at 9:34 AM
    Thursday at 9:34 AM
    10/12/2017

    您还可以修改该方法以获取要比较的参考日期(而不是在该方法中使用硬编码的new LocalDate()


    Java新的日期/时间API

    Joda Time处于维护模式,正在被新的API所取代,所以我不建议用它来启动一个新项目。即使在joda's website中,它也说:“注意,Joda Time被认为是一个基本上“完成”的项目。没有计划进行重大的增强。如果使用Java SE 8,请迁移到Java.Time(JSR-310)。”

    如果使用<强> java 8 < /St>,考虑使用new java.time API。更简单,less bugged and less error-prone than the old APIs

    如果您使用的是Java6或7,那么可以使用ThreeTen Backport,这是Java8新的日期/时间类的一个很好的后台端口。对于Android,您还需要ThreeTenABP(更多关于如何使用它的信息here

    下面的代码适用于这两种情况。 唯一的区别是包名(在Java 8中是^{),在ThreeTen Backport(或Android的ThreeTenABP)中是^{),但类和方法的名称是相同的

    此API与Joda Time非常相似,因此代码有一些细微的差异:

    static DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
    
    static DateTimeFormatter MDY_FORMAT = DateTimeFormatter.ofPattern("M/d/yyyy");
    
    public String calendar(ZonedDateTime dt) {
        StringBuilder sb = new StringBuilder();
    
        // check difference in days from today, considering just the date (ignoring the hours) 
        long days = ChronoUnit.DAYS.between(LocalDate.now(), dt.toLocalDate());
        if (days == 0) { // today
            sb.append("Today ");
        } else if (days == 1) { // tomorrow
            sb.append("Tomorrow ");
        } else if (days == -1) { // yesterday
            sb.append("Yesterday ");
        } else if (days > 0 && days < 7) { // next week
            sb.append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
        } else if (days < 0 && days > -7) { // last week
            sb.append("Last ").append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
        }
    
        if (Math.abs(days) < 7) {  // difference is less than a week, append current time
            sb.append("at ").append(dt.format(HOUR_FORMAT));
        } else { // more than a week of difference
            sb.append(dt.format(MDY_FORMAT));
        }
    
        return sb.toString();
    }
    

    我使用了乔达的ZonedDateTimewhich is an equivalent(它代表时区中的日期和时间)

    调用DAYS.between时,我将其转换为LocalDate,因此比较只考虑日期(日/月/年)。如果我用ZonedDateTime来代替,时间也会被考虑,因此只有当时间超过24小时时,结果才是1天(所以你可以根据需要更改它)

    注意,我还必须创建两个DateTimeFormatter实例。我在方法之外创建了它们,因此它们可以重用(不需要一直在方法内部创建它们)。Joda Time不需要它,因为Joda对象中的toString方法可以采用模式并在内部创建格式化程序,而在java.timeAPI中必须显式创建格式化程序

    使用它也类似于Joda Time:

    ZonedDateTime now = ZonedDateTime.now();
    System.out.println(calendar(now.minusDays(10))); // 9/22/2017
    System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
    System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
    System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
    System.out.println(calendar(now)); // Today at 9:34 AM
    System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
    System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
    System.out.println(calendar(now.plusDays(10))); // 10/12/2017
    

    只是一个关于时区的说明。在java.timeAPI中,所有日期类都有一个no-arg now()方法,该方法获取JVM默认时区中的当前日期/时间

    虽然它非常方便,但也有一些缺点,因为默认时区可以在不通知的情况下更改,即使在运行时也是如此。如果可能的话,最好指定你想要的时区

    API使用IANA timezones names(始终采用Region/City格式,如America/New_YorkEurope/Paris)。 避免使用三个字母的缩写(如CETEST),因为它们是ambiguous and not standard

    你可以通过调用ZoneId.getAvailableZoneIds()获得可用时区的列表(并选择最适合你的系统的时区)

    要获取特定时区中的当前日期/时间,请使用ZoneId类:

    // get the current date/time in a specific timezone
    ZonedDateTime.now(ZoneId.of("Europe/Paris"));
    
  2. # 2 楼答案

    爪哇。时间

    现代方法使用业界领先的java。时间课

    ZoneId z = ZoneId.now( “America/Montreal”  ) ;
    LocalDate today = LocalDate.now( z ) ;
    

    用加减法来做数学题

    LocalDate tomorrow = today.plusDays( 1 ) ;
    

    搜索堆栈溢出。几乎每个基本的日期时间问题都已经被问到了

    爪哇。时间类不会生成诸如“明天”和“上周一”之类的字符串。因此,没有直接等效的参考库。你得自己干农活

    搜索^{}类和^{}

    此外,^{}enum及其自动本地化^{}方法可能有用

    美好时光

    虽然我还没用过prettytime库,但它可能会帮助你

    乔达时间

    Joda Time项目处于维护模式。该团队建议迁移到java。时间课


    关于java。时间

    java.time框架内置于Java8和更高版本中。这些类取代了legacy日期时间类,比如^{}^{}、&^{}

    目前位于maintenance modeJoda-Time项目建议迁移到java.time

    要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和解释。规格是JSR 310

    在哪里可以获得java。时间课

    ThreeTen-Extra项目扩展了java。有额外课程的时间。这个项目是java未来可能增加的一个试验场。时间你可以在这里找到一些有用的类,比如^{}^{}^{}more