使用日历填写空日期

时间:2016-03-19 18:59:47

标签: java date datetime

我正在尝试创建一个基于用户的开始和结束日期的日期列表。这是我在我的数组中的信息:

Calendar start = new GregorianCalendar(2015, 01, 01);
Calendar end = new GregorianCalendar(2015, 05, 01);
//User defined start and end time simulation

List<Calendar> datesinDB = new ArrayList<Calendar>();
datesinDB.add(new GregorianCalendar(2015,02,15));
datesinDB.add(new GregorianCalendar(2015,02,16));
datesinDB.add(new GregorianCalendar(2015,02,17));
datesinDB.add(new GregorianCalendar(2015,02,19));
datesinDB.add(new GregorianCalendar(2015,02,20));
datesinDB.add(new GregorianCalendar(2015,02,22));
datesinDB.add(new GregorianCalendar(2015,03,10));
datesinDB.add(new GregorianCalendar(2015,03,25));
datesinDB.add(new GregorianCalendar(2015,03,27));
//This is the data that I have in my simulated database

我的代码:

Calendar c = datesinDB.get(count-1);
    for(int i = 1; i < datesinDB.get(0).getActualMaximum(datesinDB.get(0).DAY_OF_MONTH); i++){
        if(i == c.get(5) && count < datesinDB.size())
        {

            revised.add(new GregorianCalendar(c.YEAR, c.MONTH, c.get(5)));
            System.out.println(c.get(5));
            c = datesinDB.get(count++);
        }
        else
        {
            revised.add(new GregorianCalendar(c.YEAR, c.MONTH, i));
        }
    }

输出:

Tue Feb 01 00:00:00 SGT 1
Wed Feb 02 00:00:00 SGT 1
Thu Feb 03 00:00:00 SGT 1
Fri Feb 04 00:00:00 SGT 1
Sat Feb 05 00:00:00 SGT 1
Sun Feb 06 00:00:00 SGT 1
Mon Feb 07 00:00:00 SGT 1
Tue Feb 08 00:00:00 SGT 1
Wed Feb 09 00:00:00 SGT 1
Thu Feb 10 00:00:00 SGT 1
Fri Feb 11 00:00:00 SGT 1
Sat Feb 12 00:00:00 SGT 1
Sun Feb 13 00:00:00 SGT 1
Mon Feb 14 00:00:00 SGT 1
Tue Feb 15 00:00:00 SGT 1
Wed Feb 16 00:00:00 SGT 1
Thu Feb 17 00:00:00 SGT 1
Fri Feb 18 00:00:00 SGT 1
Sat Feb 19 00:00:00 SGT 1
Sun Feb 20 00:00:00 SGT 1
Mon Feb 21 00:00:00 SGT 1
Tue Feb 22 00:00:00 SGT 1
Wed Feb 23 00:00:00 SGT 1
Thu Feb 24 00:00:00 SGT 1
Fri Feb 25 00:00:00 SGT 1
Sat Feb 26 00:00:00 SGT 1
Sun Feb 27 00:00:00 SGT 1
Mon Feb 28 00:00:00 SGT 1

我的问题是我的代码只能在一个月内完成,而不再是。有办法解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

使用常数是不好的形式,在final Calendar start = Calendar.getInstance(2015, 1, 1); final Calendar end = Calendar.getInstance(2015, 5, 1); final List<Calendar> dates = new ArrayList<>(128); // 128: fewer reallocations for (Calendar date = start; !date.after(end); date.add(Calendar.DATE, 1)) { dates.add(date); } 类中查找要使用的常量的符号名称。

这是我认为你想要的:

principalStage

答案 1 :(得分:1)

该问题及其代码令人困惑。作者没有准确说明问题所在。而且我不能完全遵循代码的逻辑。您的输出不会映射到您的代码。您是否尝试计算数据库中每天有多少行落在日期范围的每一天?您是否尝试获取日期范围内出现的数据库行的子集?所以我无法给出一个完美的答案,但我会让你更接近解决方案。

八路

请勿填充前导零的数字文字;告诉Java将文字解释为Octal(base-8)而不是Decimal(base-10)。因此,( 2015 , 02 , 15 )应为( 2015 , 2 , 15 )

避免旧的日期时间类

您不应该使用与最早版本的Java捆绑在一起的旧日期时间类。事实证明,它们设计糟糕,令人困惑且麻烦。

java.time

旧的类被Java 8及更高版本中内置的java.time框架所取代。请参阅Tutorial

LocalDate

java.time类包括java.time.LocalDate,以真正表示没有时间且没有时区的仅限日期的值。似乎是你需要的。要从数据库中获取它们,请通过JDBC使用java.sql.Date类。尽量减少使用java.sql;当您继续使用业务逻辑和演示文稿时,立即从java.sql类型转换为java.time。在您的数据库中,将列定义为DATE类型。

List < LocalDate > datesInQuestion = new ArrayList <> ( );
datesInQuestion.add ( LocalDate.of ( 2015, 2, 20 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 2, 22 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 3, 10 ) );
datesInQuestion.add ( LocalDate.of ( 2015, 12, 31 ) );

YearMonth

对于边界(开始 - 停止),如果仅使用整个月,则传递java.time.YearMonth类的对象。

YearMonth startYearMonth = YearMonth.of ( 2016, Month.JANUARY );
YearMonth stopYearMonth = YearMonth.of ( 2016, Month.JUNE ); 

半开

在日期时间工作中,通常使用半开放方法表示时间跨度。开头是包含,而结尾是独占。在问题的例子之后,我们将从1月到6月运行,以便包括整个5月。

LocalDate start = startYearMonth.atDay ( 1 );
LocalDate stop = stopYearMonth.atDay ( 1 );  // Half-open approach, running up to but not including this date.

准备一对列表以存储在我们的范围内找到的日期,并存储在我们的目标列表中找不到匹配项的日期。

List < LocalDate > datesInRange = new ArrayList <> ( );
List < LocalDate > datesVoid = new ArrayList <> ( );

将每个日期循环到我们的范围内。在我们的目标列表中搜索任何匹配项。

LocalDate localDate = start;
while ( localDate.isBefore ( stop ) ) { // Loop through our date range from 'start' to 'stop', with 'stop' being exclusive.
    if ( datesInQuestion.contains ( localDate ) ) {
        datesInRange.add ( localDate );
    } else {
        datesVoid.add ( localDate );
    }

也许你想知道这个日期出现在'datesInQuestion'集合中的次数。 Collections.frequency实用程序类(注意结尾的's')

    int frequency = Collections.frequency ( datesInQuestion, localDate );

设置下一个循环。增加到下一个日期。

    localDate = localDate.plusDays ( 1 );
}

此时循环已完成。

也许您想知道超出我们范围的目标日期。复制有问题的日期列表。删除发现在我们范围内的那些。剩下的必须在范围之外。

List < LocalDate > datesOutsideRange = new ArrayList <> ( datesInQuestion ); // Duplicate the collection of dates-in-question.
boolean anyRemoved = datesOutsideRange.removeAll ( datesInRange );  // Then remove the ones found to be within our range.

转储到控制台。

System.out.println ( "datesInQuestion: " + datesInQuestion );
System.out.println ( "datesInRange: " + datesInRange );
System.out.println ( "datesOutsideRange: " + datesOutsideRange );
System.out.println ( "datesVoid: " + datesVoid );
  

datesInQuestion:[2015-02-20,2015-02-22,2015-03-10,2015-12-31]

     

datesInRange:[2015-02-20,2015-02-22,2015-03-10]

     

datesOutsideRange:[2015-12-31]

请注意我们2月20日的三个日期&amp; 22和3月10日不会出现在datesVoid这个较长的列表中。

  

datesVoid:[2015-01-01,2015-01-02,2015-01-03,2015-01-04,2015-01-05,2015-01-06,2015-01-07,2015- 01-08,2015-01-09,2015-01-10,2015-01-11,2015-01-12,2015-01-13,2015-01-14,2015-01-15,2015-01- 16,2015-01-17,2015-01-18,2015-01-19,2015-01-20,2015-01-21,2015-01-22,2015-01-23,2015-01-24, 2015-01-25,2015-01-26,2015-01-27,2015-01-28,2015-01-29,2015-01-30,2015-01-31,2015-02-01,2015- 02-02,2015-02-03,2015-02-04,2015-02-05,2015-02-06,2015-02-07,2015-02-08,2015-02-02,2015-02- 10,2015-02-11,2015-02-12,2015-02-13,2015-02-14,2015-02-15,2015-02-16,2015-02-17,2015-02-18, 2015-02-19,2015-02-21,2015-02-23,2015-02-24,2015-02-25,2015-02-26,2015-02-27,2015-02-28,2015- 03-01,2015-03-02,2015-03-03,2015-03-04,2015-03-05,2015-03-06,2015-03-07,2015-03-08,2015-03-03- 09,2015-03-11,2015-03-12,2015-03-13,2015-03-14,2015-03-15,2015-03-16,2015-03-17,2015-03-18, 2015-03-19,2015-03-20,2015-03-21,2015-03-22,2015-03-23,2015-03-24,2015-03-25,2015-03-26,2 015-03-27,2015-03-28,2015-03-29,2015-03-30,2015-03-31,2015-04-01,2015-04-02,2015-04-03,2015- 04-04,2015-04-05,2015-04-06,2015-04-07,2015-04-08,2015-04-09,2015-04-10,2015-04-11,2015-04- 12,2015-04-13,2015-04-14,2015-04-15,2015-04-16,2015-04-17,2015-04-18,2015-04-19,2015-04-20, 2015-04-21,2015-04-22,2015-04-23,2015-04-24,2015-04-25,2015-04-26,2015-04-27,2015-04-28,2015- 04-29,2015-04-30,2015-05-01,2015-05-02,2015-05-03,2015-05-04,2015-05-05,2015-05-06,2015-05-05- 07,2015-05-08,2015-05-09,2015-05-10,2015-05-11,2015-05-12,2015-05-13,2015-05-14,2015-05-15, 2015-05-16,2015-05-17,2015-05-18,2015-05-19,2015-05-20,2015-05-21,2015-05-22,2015-05-23,2015- 05-24,2015-05-25,2015-05-26,2015-05-27,2015-05-28,2015-05-29,2015-05-30,2015-05-31]

答案 2 :(得分:1)

我在发布问题之后看了joda-time后确实弄清楚了,所以这里是:

解决方案是使用joda-time计算一年中的日期而不是使用日期,月份和年份的原始方式。

我的实际目标是填充缺少日期,这些日期不在模拟的ArrayList中,模拟从某个实际数据库中获取的数据。所以它可能看起来像这样:

Date     | Value
15/02/15 | 1
16/02/15 | 2
18/02/15 | 3
19/02/15 | 6

我的目标是创建一个arraylist,如果我的原始数据库中不存在日期,那么该月份的所有日期值为0。填写的月数由开始和结束日期确定,因此假设在这种情况下,我要求做一个月。

Date       | Value
01/02/2015 | 0
02/02/2015 | 0
03/02/2015 | 0
04/02/2015 | 0
05/02/2015 | 0
06/02/2015 | 0
07/02/2015 | 0
08/02/2015 | 0
09/02/2015 | 0
10/02/2015 | 0
11/02/2015 | 0
12/02/2015 | 0
13/02/2015 | 0
14/02/2015 | 0
15/02/2015 | 1
16/02/2015 | 2
17/02/2015 | 0
18/02/2015 | 3
19/02/2015 | 6
20/02/2015 | 0
21/02/2015 | 0
22/02/2015 | 0
23/02/2015 | 0
24/02/2015 | 0
25/02/2015 | 0
26/02/2015 | 0
27/02/2015 | 0
28/02/2015 | 0

以下是我修改后的代码:

DateTimeFormatter sdf = DateTimeFormat.forPattern("dd/MM/yyyy");//formatter for display
LocalDate start = new LocalDate(2015, 01, 01);
LocalDate end = new LocalDate(2015, 06, 01);
List<Dates> revised = new ArrayList<Dates>(); //populated array
List<Dates> datesinDB = new ArrayList<Dates>(); //
int count = 1; //index for arrays
datesinDB.add(new Dates(new LocalDate(2015,02,15), 1)); //data
datesinDB.add(new Dates(new LocalDate(2015,02,16), 2));
datesinDB.add(new Dates(new LocalDate(2015,02,17),22));
datesinDB.add(new Dates(new LocalDate(2015,02,19),14));

LocalDate c = datesinDB.get(count-1).getDate(); //initial data
int values = datesinDB.get(count-1).getValue(); //initial data

for(int i = start.getDayOfYear(); i <=end.getDayOfYear() ; i++){
    if(i == c.getDayOfYear())
    {
        if(count < datesinDB.size()){
            revised.add(new Dates(c, values));
            c = datesinDB.get(count).getDate();
            values = datesinDB.get(count++).getValue();
        }
        else if(count == datesinDB.size()){
            revised.add(new Dates(c, values));
            count++;
        }
    }
        else
        {
            if(i != 59){//some issues with 28/2/2015 due to leap year i guess
                revised.add(new Dates(new      LocalDate().withDayOfYear(i).withYear(2015), 0));
           }
        }
   }

    System.out.println("Date      | Values");
    for(int i = 0; i< revised.size(); i++){
        System.out.println(sdf.print(revised.get(i).getDate())+ " | "+ revised.get(i).getValue());
    }

总而言之,这会让我知道我需要的一些细微的错误,我会解决。感谢那些回答。

Fyi,Dates是我的LinkedList类,如下所示:

public class Dates {
    public LocalDate date;
    public int value;

    public Dates(LocalDate date, int value){
        this.date = date;
        this.value = value;
    }

    public LocalDate getDate(){
        return this.date;
    }

    public int getValue(){
        return this.value;
    }
}

我希望如果他们与我在同一水域,这会帮助别人。神圣的地狱365天很难掌握。