从给定月份计算前 12 个月 - SimpleDateFormat

Calculate previous 12 months from given month - SimpleDateFormat

我正在尝试将给定月份(取自数据库)的前 12 个月放入数组列表中。

List<String> allDates = new ArrayList<String>();    

sqlQuery="select max(date) from Table_Name";

maxDate="Jan-2016"; (Result from Query);

要从 maxDate 获取前 12 个月,我使用 SimpleDateFormat。

我想从 给定月份 (maxDate) 开始计算前 12 个月,而不是从当前月份开始,我尝试了以下代码。

//  Parsing maxDate to an integer (say Jan-2016 = 0, Feb-2016= 1)
Date date = new SimpleDateFormat("MMM-yyyy").parse(maxDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month=cal.get(Calendar.MONTH);
        System.out.println("month : "+month);

// Looping to get previous 12 months from current month.
SimpleDateFormat month_date = new SimpleDateFormat("MMM-yyyy");
          for (int i = 12; i > 0; i--) {
                Calendar calendar1 = Calendar.getInstance();
                calendar1.add(Calendar.MONTH, -i);
                String month_name1 = month_date.format(calendar1.getTime());
                allDates.add(month_name1);
            }
            System.out.println(allDates);

由于月份是从 (0 - 11) 开始编号的,所以我无法实现。 请提出一个想法来计算给定月份的前 12 个月。感谢您的帮助!

问题在于,在循环中,您始终根据当前日期而不是 maxDate.

进行计算
List<String> allDates = new ArrayList<>();
String maxDate = "Jan-2016";
SimpleDateFormat monthDate = new SimpleDateFormat("MMM-yyyy");
Calendar cal = Calendar.getInstance();
cal.setTime(monthDate.parse(maxDate));
for (int i = 1; i <= 12; i++) {
    String month_name1 = monthDate.format(cal.getTime());
    allDates.add(month_name1);
    cal.add(Calendar.MONTH, -1);
}
System.out.println(allDates);

输出

[Jan-2016, Dec-2015, Nov-2015, Oct-2015, Sep-2015, Aug-2015, Jul-2015, Jun-2015, \
 May-2015, Apr-2015, Mar-2015, Feb-2015]

编辑 简短说明代码段的作用。

  1. 从给定的 maxDate 创建一个 Calendar 并将其分配给 cal
  2. cal中当前日期的字符串Mon-Year添加到列表allDates
  3. 从日历中减去一个月cal.add(Calendar.MONTH, -1)
  4. 重复第 2 步和第 3 步十二次

正如 Basil 所提到的。如果您想稍后将 allDates 中的值处理为 Date / Calendar,请考虑不要在两者之间生成字符串列表。

ISO 8601

将日期时间值表示为文本有一个合理的标准:ISO 8601

因此,与其将年月值序列化为 Jan-2016,我强烈建议您使用标准格式 2016-01。即使跨英语以外的语言阅读这种格式也很直观。

java.time

您正在使用与 Java 的最早版本捆绑在一起的麻烦的旧日期时间 classes。如您所知,他们糟糕的设计选择之一是从零开始的月份数字 运行 0-11.

Sun 和 Oracle 放弃了那些旧的 classes,取而代之的是 Java 8 及更高版本中内置的 java.time 框架。

YearMonth

其中 classes 正是您所需要的:YearMonth。顾名思义,年和月的组合。

不是处理字符串,而是传递这种类型的对象。鉴于 class 内置于 Java.

中,您可以在整个代码库中依赖此 class

解析

要解析您的非标准字符串,请定义格式化程序。为翻译月份名称的人类语言指定 Locale

DateTimeFormatter formatter = formatter.ofPattern( "MMM-yyyy" );
formatter = formatter.withLocale( Locale.US ) ;
YearMonth stop = YearMonth.parse( "Jan-2016" , formatter );

要解析标准字符串,不需要格式化程序。 java.time classes 默认支持 parsing/generating ISO 8601 字符串。

YearMonth stop = YearMonth.parse( "2016-01" );

日期时间数学

YearMonth class 提供了加减时间的方法。

YearMonth start = stop.minusYears( 1 );

定义类型为 YearMonth 的集合。

List<YearMonth> yearMonths = new ArrayList<>( 12 );

循环,每次递增一个月,直到到达停止月份。您要求 Half-Open 方法,其中时间跨度的开始是 inclusive 而结束是 exclusive。这种半开方法在日期时间工作中很常见。

YearMonth yearMonth = start ;
while ( yearMonth.isBefore( stop ) ) {
    yearMonths.add( yearMonth ) ;  // Add each incremented YearMonth to our collection.
    // Set up next loop.
    yearMonth = yearMonth.plusMonths( 1 );
}
public static void main(String[] args) {        
    Calendar c = Calendar.getInstance();
    c.setTime(new Date()); //Give Your Date
    c.add(Calendar.MONTH, -12);
    Date fromDate = c.getTime();
    Date toDate = new Date(); //Give Your Date

    System.out.println("from "+fromDate);
    System.out.println(" to "+fromDate);
}

SQL 查询:

select * from TABLE where Date between fromDate and toDate;