java - 创建自己的周期类时遇到困难

标签 java calendar period milliseconds

我在建立自己的时期类(class)时遇到了一些困难,我知道那里已经有一些类(class),但由于内部限制,我将不得不实现自己的类(class)。 构造函数(下面的代码)基本上接受2个日期,一个开始和一个结束,方法makeWeeks(),会将这段时间划分为几周,我根据我在学习列表时学到的“头尾”原则开发了这个。

这是代码(要点)

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;
  }

恐怕有问题,这在大多数情况下工作正常,但在某些情况下(例如 2011 年 11 月和 12 月)不会收集第二周,并且在 2012 年 3 月,如果您设置为 endDate 31/Mar/2012,则不会收集最后一周,但如果您选择结束日期 30/Mar/2012,则不会收集。 您有什么建议吗?

最佳答案

解决了!

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());
    }
  }
}

关于java - 创建自己的周期类时遇到困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10813676/

相关文章:

java - 我想获取一年中的所有星期以及从当前日期开始的java中每周的开始和结束工作日日期?

java - 我们可以在java中设置特定的时间吗

regex - 正则表达式 Perl 期间引用

Java时间戳正则表达式

java - 如何模拟 RestTemplate 的 webservice 响应?

java.lang.NoClassDefFoundError : javax/servlet/http/HttpServletRequest 错误

java - GregorianCalendar 的另一种奇怪行为

ios - Iphone加速度计采样频率

send - RTCP接收方报告发送间隔

java - YamlDotNet:如何处理!!set