繁体   English   中英

Java:在Calendar对象中设置日期时,我可以使用日/月/年参考吗?

[英]Java: when setting a date in a Calendar object, can I use day/month/year references?

我是Java世界的新手,我练习了很多。 我最后一次锻炼是关于公寓租赁计划。 我的问题是指Manager类中的“预订”部分,我必须检查所请求的到达日期是否与阵列双重关税[]中的低,中,高季节相关联。

以下是使用bookApartment()方法的代码部分,其中codeid是HashMaps of Apartments and Clients中的密钥(仅当到达日期为星期六时,预订才正确):

public Booking bookAppartment(String code, String id, int day, int month, int year, int nweeks) throws WrongDay {
    Calendar date = Calendar.getInstance();
    date.set(year, month-1, day);
    int weekday = date.get(Calendar.DAY_OF_WEEK);
    Booking book=null;
    if(code!="" && id!=""){
        if(weekday!=Calendar.SATURDAY)
            throw new WrongDay(date);
        else{
            for(Map.Entry<String , Apartment> apt : apts.entrySet()){
                for(Map.Entry<String, Client> client : clients.entrySet()){
                    if(apt.getKey()==code && client.getKey()==id && weekday==Calendar.SATURDAY){
                        book = new Booking(client.getValue(), apt.getValue(), d, m, y, nweeks);
                        bookings.add(book);
                        book.setPrice(d, m, y, apt.getValue().getTariffs(), nweeks);
                        break;
                    }
                }
            }
        }
    }   
    return book;
}

在这里,我附加了Booking对象的构造函数和我的setPrice()方法的个人覆盖,它计算整个预订价格,选择正确的关税[]批次:

public class Booking {

    private Client client;
    private Apartment apt;
    private double price;
    private int numweeks;
    private static int day, month, year;

    public Booking(Client client, Apartment apt, int day, int month, int year, int numweeks){
        this.client = client;
        this.apt = apt;
        Booking.day = day;
        Booking.month = month;
        Booking.year = year;
        this.numweeks = numweeks;
    }

    // other stuff 

    public void setPrice(int day, int month, int year, double[] tariff, int numweeks){
        tariff = apt.getTariffs();
        Booking.day=day;
        Booking.month=month;
        Booking.year=year;

        Calendar date = Calendar.getInstance();
        date.set(year, month-1, day);
        Calendar date1 = Calendar.getInstance();
        date1.set(2008, 6, 1);
        Calendar date2 = Calendar.getInstance();
        date2.set(2008, 6, 31);
        Calendar date3 = Calendar.getInstance();
        date3.set(2008, 7, 1);
        Calendar date4 = Calendar.getInstance();
        date4.set(2008, 7, 31);
        Calendar date5 = Calendar.getInstance();
        date5.set(2008, 11, 20);
        Calendar date6 = Calendar.getInstance();
        date6.set(2009, 0, 1);

        if(date.equals(date1) || date.equals(date2) || (date.after(date1) && date.before(date2))){
            this.price = tariff[1] * numweeks;
        } else if(date.equals(date3) || date.equals(date4) || (date.after(date3) && date.before(date4))){
            this.price = tariff[2] * numweeks;
        } else if(date.equals(date5) || date.equals(date6) || (date.after(date5) && date.before(date6))){   
            this.price = tariff[2] * numweeks;
        } else{
            this.price = tariff[0] * numweeks;
        }

    }    
}

与20日2008年12月(考虑旺季)抵达日期设置预约对象的价格时,我遇到的问题:它会跳过如果检查(预期)第三,直接进入到最后的

但是如果我运行自己的程序来检查日期是否相同,直接将值传递给日,月和年,则测试通过。

所以在我看来,我不能仅传递未指向未手动设置的int值的引用。 我有可能吗? 如果是这样,我真的不知道该怎么做。

在此先感谢:我希望我在正确的地方使用了所有正确的词语。

当您获得日历实例时,它默认使用当前时间(直到毫秒)。 因此,当您在其中设置日期时:

Calendar date = Calendar.getInstance();
date.set(year, month-1, day);

... date仍然是小时,分钟,秒和毫秒的“随机”值。 date1date6

在您的代码中,您可以一个接一个地创建所有日期,因此执行这些指令的速度可能意味着前几个日期最终具有相同的小时,分​​钟,秒和毫秒值。 但是不能保证这一点。

您所发现的是,例如,当您执行date.equals(date3) ,年月和日匹配时,但其他字段可能不会。

要解决此问题,请先调用clear()

Calendar date = Calendar.getInstance();
date.clear();
date.set(year, month-1, day);

此外,您可能实际上并不想比较日历的相等性。 你可以,但如果你看一下它的Javadoc,它会说:

 * Compares this <code>Calendar</code> to the specified
 * <code>Object</code>.  The result is <code>true</code> if and only if
 * the argument is a <code>Calendar</code> object of the same calendar
 * system that represents the same time value (millisecond offset from the
 * <a href="#Epoch">Epoch</a>) under the same
 * <code>Calendar</code> parameters as this object.
 *
 * <p>The <code>Calendar</code> parameters are the values represented
 * by the <code>isLenient</code>, <code>getFirstDayOfWeek</code>,
 * <code>getMinimalDaysInFirstWeek</code> and <code>getTimeZone</code>
 * methods. If there is any difference in those parameters
 * between the two <code>Calendar</code>s, this method returns
 * <code>false</code>.
 *
 * <p>Use the {@link #compareTo(Calendar) compareTo} method to
 * compare only the time values.

你可能最好使用:

if (date.getTime().equals(date1.getTime()))
{
  ...
}

...并比较返回的Date对象,或者像Javadoc建议的那样并使用compareTo()

if (date.compareTo(date1) == 0)
{
  ...
}

我知道你正在做练习,但你应该知道:

(a)避免使用java.util.Calendar

与Java捆绑在一起的java.util.Date和.Calendar类非常麻烦。 避免他们。 使用与Java 8捆绑在一起的新java.time包 ,或者启发java.time的Joda-Time库。 java.time和Joda-Time都有一些优点和缺点,两者都是活动项目,你甚至可以在项目中使用它们。

(b)仅限日期

旧的.Date和.Calendar类缺少日期表示,没有时间。 但这就是你的问题所要求的,这是一个仅限日期而没有时区的课程。 幸运的是,Joda-Time和java.time都有这样一个类,都叫做LocalDate

(c)半开放

跨越时间跨度的最佳方法称为“半开放”,其中开头是包容性的,结尾是排他性的。 例如,6月份的月份将是6月1日,但不包括7月1日。这简化了日期工作或日期工作。 Joda-Time和java.time采用这种方法。

Greg Kopff另一个答案似乎是正确的,时间部分会让你失望。

以下是Joda-Time 2.4中的一些示例代码,可帮助您朝着正确的方向前进。

LocalDate target = new LocalDate( 2008, 12, 20 );

LocalDate highSummerStart = new LocalDate( 2008, 6, 1 );  // Half-Open. Inclusive.
LocalDate highSummerStop = new LocalDate( 2008, 7, 1 );  // Exclusive.

LocalDate lateSummerStart = new LocalDate( 2008, 7, 1 );  // Half-Open. Inclusive.
LocalDate lateSummerStop = new LocalDate( 2008, 8, 1 );  // Exclusive.

LocalDate holidaysStart = new LocalDate( 2008, 11, 20 );  // Half-Open. Inclusive.
LocalDate holidaysStop = new LocalDate( 2009, 1, 2 );  // Exclusive.

if ( this.rangeContainsTarget( highSummerStart, highSummerStop, target ) ) {
    System.out.println( "Apply High Summer rates." );
} else if ( this.rangeContainsTarget( lateSummerStart, lateSummerStop, target ) ) {
    System.out.println( "Apply Late Summer rates." );
} else if ( this.rangeContainsTarget( holidaysStart, holidaysStop, target ) ) {
    System.out.println( "Apply Holidays rates." );
} else { // Else not in special season.
    System.out.println( "Apply default rates." );
}

和比较方法。

private boolean rangeContainsTarget( LocalDate start, LocalDate stop, LocalDate target )
{
    // Half-Open approach. If the Target is GREATER THAN OR EQUAL TO Start AND Target is LESS THAN Stop.
    if ( start.isAfter( stop ) ) {
        return false; // Or throw exception.
    }
    boolean startGood = ( target.isEqual( start ) || target.isAfter( start ) );
    boolean stopGood = target.isBefore( stop );
    boolean containsTarget = ( startGood && stopGood );
    return containsTarget;
}

旧的.Date / .Calendar类缺少表示时间跨度的方法。 Joda-Time提供三个类来以各种方式定义时间跨度:间隔,周期和持续时间。 不幸的是,它们仅适用于DateTime,而不适用于LocalDate。 所以我没有在上面的例子中使用它们,其中Interval会很方便。


顺便说一句,如果在Joda-Time中你确实需要一个日期加上时间而又想要关注几天,请调用withTimeAtStartOfDay()方法将DateTime对象设置为当天的第一个时刻。 第一个时刻并不总是时间00:00:00.000因为夏令时和其他异常现象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM