简体   繁体   English

在创建自己的Period类时遇到困难

[英]Hard time while creating my own Period class

I'm having some hard time building my own period class, i know that there are some already made classes out there but due to internal restrictions i will have to implement my own. 我在建立自己的周期类时遇到了一些困难,我知道那里已经有一些已经完成的类,但是由于内部限制,我将不得不实现自己的类。 The constructor (code below) basically accepts 2 dates, a start and an end, the method makeWeeks(), will devide this period into weeks, i developed this according to the "head-tail" principle that i learned when i was studying lists. 构造函数(下面的代码)基本上接受2个日期,一个开始和一个结束,方法makeWeeks()将这段时间划分为几个星期,我根据我在学习列表时学到的“头尾”原理开发了这个日期。

heres the code (the essentials) 继承人代码(要点)

public class Period implements Serializable
{
  private static final long serialVersionUID = 1L;

  private Calendar          start;

  private Calendar          end;

  private long              durationMillis;

  private long              startMillis;

  private long              endMillis;

  private long              MAX              = 604800000; //A week in millis

  private long              DAY              = 86400000;

  private long              SIX              = 518400000;

  private ArrayList<Week>   weeks;


  public Period(Calendar start, Calendar end)
  {

    this.start = start;
    this.end = end;
    startMillis = start.getTimeInMillis();
    endMillis = end.getTimeInMillis();
    durationMillis = endMillis - startMillis;
    int startWeek = start.get(Calendar.WEEK_OF_YEAR);
    int endWeek = end.get(Calendar.WEEK_OF_YEAR);
    weeks = new ArrayList<Week>();

  }

  /**
   * Construct the weeks in this period
   * 
   * @return
   */
  public ArrayList<Week> makeWeeks()
  {
    long borderLine;

    if ((durationMillis < MAX) || (endMillis < startMillis))
    {
      return null;
    }
    Calendar endHead = Calendar.getInstance();
    //If first week is not Monday then count the days that have been completed
    if (start.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY)
    {
      int days = 0;
      start = adjustCalendar(start);//Set time to 0:0:0:0
      days = getDaysToMonday(start.get(Calendar.DAY_OF_WEEK));
      endHead.setTimeInMillis(start.getTimeInMillis());
      endHead.add(Calendar.DAY_OF_YEAR, days - 1);
      weeks.add(new Week(start, endHead, days, calcCompletion(days), setWeekNumber(start)));//was endHead
      borderLine = endHead.getTimeInMillis() + DAY;
    }//head week set

    else
    {
      start = adjustCalendar(start);
      endHead.setTimeInMillis(start.getTimeInMillis());//Successful
      borderLine = endHead.getTimeInMillis();
    }

    long endMillis = 0;

    while ((((borderLine + SIX)) < (end.getTimeInMillis() + 1)))
    {

      Calendar endNext = Calendar.getInstance();
      Calendar begin = Calendar.getInstance();
      begin.setTimeInMillis(borderLine);
      endNext.setTimeInMillis(borderLine + SIX);

      weeks.add(new Week(begin, endNext, 7, true, setWeekNumber(begin)));
      borderLine += MAX;
      endMillis = endNext.getTimeInMillis();
    }
    //adjust Tail

    Calendar tail = Calendar.getInstance();
    tail.setTimeInMillis(endMillis + DAY);//the beginning of the tail

    tail = adjustCalendar(tail);//set to 00:00:00

    int daysTail = getDaysToTail(end.get(Calendar.DAY_OF_WEEK) + 1);
    if (daysTail != 0)
    {
      weeks.add(new Week(tail, end, daysTail, calcCompletion(daysTail), setWeekNumber(end)));
    }
    return weeks;
  }//EOF makeweeks


  private int setWeekNumber(Calendar cal)
  {

    return cal.get(Calendar.WEEK_OF_YEAR);
  }

  /**
   * This method returns the amount of days between the given day and the next coming Monday
   */
  private int getDaysToMonday(int currentDay)
  {

    switch (currentDay)
    {

      case 1://sunday
        return 1;

      case 2://monday
        return 0;

      case 3://tuesday
        return 6;

      case 4://wednesday
        return 5;

      case 5://thursday
        return 4;

      case 6://friday
        return 3;

      case 7://saturday
        return 2;
    }
    return 0;

  }//EOF method

  /**
   * Returns the day to the end of the final week, always start counting from a Monday
   * 
   * @return
   */
  private int getDaysToTail(int tailDay)
  {

    switch (tailDay)
    {

      case 1://sunday
        return 0;

      case 2://monday
        return 1;

      case 3://tuesday
        return 2;

      case 4://wednesday
        return 3;

      case 5://thursday
        return 4;

      case 6://friday
        return 5;

      case 7://saturday
        return 6;
    }

    return 0;

  }

  /**
   * Returns the amount of weeks stored in this period, completed and non
   * 
   * @return
   */
  public int totalWeeks()
  {
    return weeks.size();
  }

  /**
   * Tells us if the selected period is at least one week
   * will return no result.
   * 
   * @return
   */
  public boolean isAtleastWeek()
  {
    long diff = end.getTimeInMillis() - start.getTimeInMillis();
    if (diff < MAX)
    {
      return false;
    }
    return true;
  }



  /**
   * Provided a week-number, gives back a Week marked by that week-number, if existing.
   * 
   * @param weekNumber
   * @return
   */
  public Week getWeek(Double weekNumber)
  {

    int weekNumberInt = weekNumber.intValue();
    for (Week week : weeks)
    {
      if (weekNumberInt == week.getWeekNumber())
      {
        return week;
      }
    }
    return null;
  }

  /**
   * This method will set the calendars time (H:M:S:M) to 0:0:0:0 so to be able to calculate a precise start and End,
   * dates will remain unaltered
   * 
   * @param cal
   * @return
   */
  private Calendar adjustCalendar(Calendar nu)
  {

    nu.set(Calendar.HOUR, 0);
    nu.set(Calendar.MINUTE, 0);
    nu.set(Calendar.SECOND, 0);
    nu.set(Calendar.MILLISECOND, 0);

    return nu;
  }

I'm afraid there is something wrong, this works fine in most cases but in some cases, (like November and December 2011) the second week is not collected, and in March 2012 the last week is not collected if you set as endDate 31/Mar/2012 but it is if you select as end 30/Mar/2012. 恐怕出了点问题,在大多数情况下都可以,但是在某些情况下(例如,2011年11月和2011年12月),第二周不收集,如果您设置为endDate 31,则在2012年3月不收集最后一周/ Mar / 2012,但如果您选择将其作为30 / Mar / 2012结尾。 Do you have any advice? 您有什么建议吗?

Solved! 解决了!

public class Period implements Serializable
{
  private static final long serialVersionUID = 1L;

  private Calendar          start;

  private Calendar          end;

  private Calendar          startClone;

  private Calendar          endClone;

  private long              durationMillis;

  private long              startMillis;

  private long              endMillis;

  private long              MAX              = 604800000; //A week in millis

  private long              DAY              = 86400000;

  private long              SIX              = 518400000;

  private ArrayList<Week>   weeks;

  /**
   * Constructor accepts 2 Calendars
   * 
   * @param start
   * @param end
   */
  public Period(Calendar start, Calendar end)
  {

    this.start = start;
    this.end = end;
    startClone = (Calendar)start.clone();
    endClone = (Calendar)end.clone();
    startMillis = start.getTimeInMillis();
    endMillis = end.getTimeInMillis();
    durationMillis = endMillis - startMillis;
    int startWeek = start.get(Calendar.WEEK_OF_YEAR);
    int endWeek = end.get(Calendar.WEEK_OF_YEAR);
    weeks = new ArrayList<Week>();

  }

  /**
   * Construct the weeks in this period
   * 
   * @return
   */
  public ArrayList<Week> makeWeeks()
  {
    Calendar borderLine;
    //The meaning of this is to report on weeks, so shorter periods wont be taken in consideration
    if ((durationMillis < MAX) || (endMillis < startMillis))
    {
      return null;
    }
    Calendar endHead = Calendar.getInstance();
    //If first week is not Monday then count the days that have been completed
    if (start.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY)
    {
      int days = 0;
      start = adjustCalendar(start);//Set time to 0:0:0:0
      days = getDaysToMonday(start.get(Calendar.DAY_OF_WEEK));
      endHead = (Calendar)start.clone();
      endHead.add(Calendar.DAY_OF_YEAR, days - 1);
      weeks.add(new Week(start, endHead, days, calcCompletion(days), setWeekNumber(start)));//was endHead
      //borderLine = endHead.getTimeInMillis() + DAY;
      Calendar vector = endHead;
      vector.add(Calendar.DAY_OF_YEAR, 1);
      borderLine = vector;
    }//head week set

    else
    {
      start = adjustCalendar(start);
      endHead = (Calendar)start.clone();//Successful
      borderLine = (Calendar)endHead.clone();
    }

    long endMillis = 0;

    while ((((borderLine.getTimeInMillis() + SIX)) < (end.getTimeInMillis() + 1)))
    {

      Calendar endNext = Calendar.getInstance();
      Calendar begin = Calendar.getInstance();
      begin = (Calendar)borderLine.clone();
      endNext = (Calendar)borderLine.clone();
      endNext.add(Calendar.DAY_OF_YEAR, 6);
      weeks.add(new Week(begin, endNext, 7, true, setWeekNumber(begin)));
      borderLine.add(Calendar.DAY_OF_YEAR, 7);
      endMillis = endNext.getTimeInMillis();
    }
    //adjust Tail

    Calendar tail = Calendar.getInstance();
    tail.setTimeInMillis(endMillis);

    tail.add(Calendar.DAY_OF_YEAR, 1);//the beginning of the tail

    if (!(tail.get(Calendar.DAY_OF_YEAR) >= end.get(Calendar.DAY_OF_YEAR)))
    {
      tail = adjustCalendar(tail);//set to 00:00:00

      int daysTail = getDaysToTail(end.get(Calendar.DAY_OF_WEEK));
      if (daysTail != 0)
      {
        weeks.add(new Week(tail, end, daysTail, calcCompletion(daysTail), setWeekNumber(end)));
      }
    }
    return weeks;
  }//EOF makeweeks

  /**
   * Get the weekNumber
   * 
   * @return
   */
  private double setWeekNumber(Calendar cal)
  {

    Integer week = cal.get(Calendar.WEEK_OF_YEAR);
    Double clone = week.doubleValue();
    return clone;
  }

  /**
   * This method returns the amount of days between the given day and the next coming Monday
   */
  private int getDaysToMonday(int currentDay)
  {

    switch (currentDay)
    {

      case 1://sunday
        return 1;

      case 2://monday
        return 0;

      case 3://tuesday
        return 6;

      case 4://wednesday
        return 5;

      case 5://thursday
        return 4;

      case 6://friday
        return 3;

      case 7://saturday
        return 2;
    }
    return 0;

  }//EOF method

  /**
   * Returns the day to the end of the final week, always start counting from a Monday
   * 
   * @return
   */
  private int getDaysToTail(int tailDay)
  {

    switch (tailDay)
    {

      case 1://sunday
        return 0;

      case 2://monday
        return 1;

      case 3://tuesday
        return 2;

      case 4://wednesday
        return 3;

      case 5://thursday
        return 4;

      case 6://friday
        return 5;

      case 7://saturday
        return 6;
    }

    return 0;

  }

  /**
   * Returns the amount of weeks stored in this period, completed and non
   * 
   * @return
   */
  public int totalWeeks()
  {
    return weeks.size();
  }

  /**
   * Tells us if the selected period is at least one week, since this is a weekly report, selecting less then a week
   * will return no result.
   * 
   * @return
   */
  public boolean isAtleastWeek()
  {
    long diff = endClone.getTimeInMillis() - startClone.getTimeInMillis();
    if (diff < MAX)
    {
      return false;
    }
    return true;
  }

  /**
   * Provide the dates(start and end of a week) in the form of a String
   * 
   * @param weekNumber
   * @return
   */
  public String getDates(Double weekNumber)
  {

    int weekNumberInt = weekNumber.intValue();

    String vector = new String();

    for (Week week : weeks)
    {
      if (week.getWeekNumber() == weekNumberInt)
      {
        vector += week.getStart().get(Calendar.DAY_OF_MONTH) + "/";
        vector += (week.getStart().get(Calendar.MONTH) + 1) + "/";
        vector += week.getStart().get(Calendar.YEAR) + "-";
        vector += (week.getEnd().get(Calendar.DAY_OF_MONTH)) + "/";
        vector += (week.getEnd().get(Calendar.MONTH) + 1) + "/";
        vector += week.getEnd().get(Calendar.YEAR);
      }
    }
    return vector;
  }

  /**
   * Provided a week-number, gives back a Week marked by that week-number, if existing.
   * 
   * @param weekNumber
   * @return
   */
  public Week getWeek(Double weekNumber)
  {

    int weekNumberInt = weekNumber.intValue();
    for (Week week : weeks)
    {
      if (weekNumberInt == week.getWeekNumber())
      {
        return week;
      }
    }
    return null;
  }

  /**
   * This method will set the calendars time (H:M:S:M) to 0:0:0:0 so to be able to calculate a precise start and End,
   * dates will remain unaltered
   * 
   * @param cal
   * @return
   */
  private Calendar adjustCalendar(Calendar nu)
  {

    nu.set(Calendar.HOUR, 0);
    nu.set(Calendar.MINUTE, 0);
    nu.set(Calendar.SECOND, 0);
    nu.set(Calendar.MILLISECOND, 0);

    return nu;
  }

  /**
   * BBC defines a week "complete" only if 4 or more days of that week have passed.
   * 
   * @param days
   * @return
   */
  private boolean calcCompletion(int days)
  {
    if (days < 4)
    {
      return false;
    }
    return true;
  }

  /**
   * @return
   */
  public boolean hasWeekNumber(Double weekNumber)
  {

    for (Week week : weeks)
    {
      if (weekNumber.intValue() == week.getWeekNumber())
      {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns the highest week number
   * 
   * @return
   */
  public double getHighestWeekNumber()
  {
    return weeks.get(weeks.size() - 1).getWeekNumber();
  }

  /**
   * Test method to print fields of a calendar
   */
  private String showCalValues(Calendar cal)
  {

    return "Day of year " + cal.get(Calendar.DAY_OF_YEAR) + " Day of month: " + cal.get(Calendar.DAY_OF_MONTH)
        + " Day of week: " + cal.get(Calendar.DAY_OF_WEEK) + " month " + cal.get(Calendar.MONTH) + " date: "
        + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.MILLISECOND)
        + " week number: " + cal.get(Calendar.WEEK_OF_YEAR) + " millis: " + cal.getTimeInMillis();
  }

  /**
   * Test method that prints the weeks
   */
  private void showWeeks()
  {
    for (Week w : weeks)
    {
      System.out.println(w.getWeekNumber() + " start millis: " + w.getStart().getTimeInMillis());
    }
  }
}

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

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