【问题标题】:Adding months to dates [closed]将月份添加到日期[关闭]
【发布时间】:2017-09-11 08:34:44
【问题描述】:

我想根据用户选择的持续时间添加月数。

我编写了以下代码,它采用当前日期并根据用户选择的持续时间添加月份,但我希望它采用从前端传递的开始日期并根据持续时间添加月份。

String le=ra.getLease_period(); //duration
String ls=ra.getLeasestart(); // start date

if (le.equals("1"))
{         
    final SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd" );
    final Date dur1 = df.parse( ls ); // conversion from String
    System.out.println("Start date passed is:" + dur1);
    String m = df.format(dur1);
    System.out.println("Formatted dur1 is" + m);
    final java.util.Calendar cal1 = GregorianCalendar.getInstance();
    cal1.setTime( date );
    cal1.add(GregorianCalendar.MONTH, 1 ); // date manipulation
    System.out.println( "result: " + df.format( cal1.getTime() ) ); 
    ra.setLeaseend(df.format( cal1.getTime() ));       
}

【问题讨论】:

  • 您是否仅限于 Java 7?最好使用 Java 8 的 java.time 包来做到这一点。
  • 为什么要将日期存储在字符串中?
  • joda.org/joda-time 如果您不使用 Java8,Joda Time 是一个很棒的库。
  • 当前输出是多少?预期的输出是什么?
  • 还有 Pra,无论您选择 Java 8 或 9 中的 java.time,Java 6 或 7 或 Joda-Time 的 ThreeTen Backport,我当然建议您放弃过时的类 SimpleDateFormat 和 @987654326 @。现代替代品更易于使用,并且都提供了更好的支持来增加日期的月份数。

标签: java date calendar date-formatting date-parsing


【解决方案1】:

感谢大家的帮助。我通过在 cal1.setTime() 函数中传递开始日期解决了这个问题。

Calendar cal1 = new GregorianCalendar();
cal1.setTime(ra.getLeasestart());
cal1.add(Calendar.MONTH, +1);
Date today1=cal1.getTime();

if(le.equals("1")){

            System.out.println("Lease end date if duratio is 1:"+today1);
            ra.setLeaseend(today1);
        }
// and so one

【讨论】:

  • 感谢您发布您的解决方案。我不得不指出,您制作的错误是您无法使用现代日期和时间库之一制作的错误。所以重复我自己:摆脱SimpleDateFormatDateCalendar,开始使用不易出错的东西。
【解决方案2】:

持续时间不应是日期。我会说它应该是一个 int(月数)。

final Integer dur1 = Integer.parseInt( le ); // conversion from String
final java.util.Calendar cal1 = GregorianCalendar.getInstance();
cal1.setTime( date );
cal1.add(GregorianCalendar.MONTH, dur1 ); // date manipulation

【讨论】:

    【解决方案3】:

    旧的类(DateCalendarSimpleDateFormat)有 lots of problemsdesign issues,它们正在被新的 API 取代。

    如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs

    如果您使用的是 Java ,则可以使用 ThreeTen Backport,这是 Java 8 新日期/时间类的一个很好的向后移植。对于Android,您还需要ThreeTenABP(详细了解如何使用它here)。

    下面的代码适用于两者。 唯一的区别是包名(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。

    首先,您可以将输入String 解析为LocalDate(使用DateTimeFormatter),然后使用plusMonths 方法添加指定的月数。最后,您使用相同的格式化程序格式化生成的日期:

    // assuming "le" and "ls" are as described in the question
    if (le.equals("1")) {
        // parse the input to a LocalDate
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate dt = LocalDate.parse(ls, fmt);
        // add 1 month
        LocalDate nextMonth = dt.plusMonths(Integer.parseInt(le));
        // print it
        System.out.println(fmt.format(nextMonth));
    }
    

    【讨论】:

      【解决方案4】:

      @StanislavL 已经回答了这个问题......所以我只是提供这个来展示一些简单的探索性测试包装:

      package time;
      
      import static org.mockito.Matchers.eq;
      import static org.mockito.Mockito.spy;
      import static org.mockito.Mockito.verify;
      import static org.mockito.Mockito.when;
      
      import java.text.ParseException;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      import java.util.GregorianCalendar;
      import org.junit.Test;
      
      public class TimeTest {
      
          @Test
          public void timeInputs1Month() throws ParseException {
              Inputs ra = spy(new Inputs("2017-09-11", "1"));
              stackOverflowQuestion(ra);
              verify(ra).setLeaseend(eq("2017-10-11"));
          }
      
          @Test
          public void timeInputs12Months() throws ParseException {
              Inputs ra = spy(new Inputs("2017-09-11", "12"));
              stackOverflowQuestion(ra);
              verify(ra).setLeaseend(eq("2018-09-11"));
          }
      
          private void stackOverflowQuestion(Inputs ra) throws ParseException {
              String le = ra.getLease_period(); //duration
              String ls = ra.getLeasestart(); // start date
      
              final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
              final Date date = df.parse(ls); // conversion from String
              System.out.println("Start date passed is:" + date);
              final java.util.Calendar cal1 = GregorianCalendar.getInstance();
              cal1.setTime(date);
              cal1.add(GregorianCalendar.MONTH, Integer.parseInt(le)); // date manipulation
              ra.setLeaseend(df.format(cal1.getTime()));
          }
      
          private class Inputs {
      
              private final String leaseStart;
              private final String leasePeriod;
      
              Inputs(String leaseStart, String leasePeriod) {
                  this.leaseStart = leaseStart;
                  this.leasePeriod = leasePeriod;
              }
      
              String getLease_period() {
                  return leasePeriod;
              }
      
              String getLeasestart() {
                  return leaseStart;
              }
      
              void setLeaseend(String leaseEnd) {
                  System.out.println("result: " + leaseEnd);
              }
          }
      }
      

      还值得注意的是SimpleDateFormat class isn't thread-safe

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多