Pandas在特定日期创建日期范围

时间:2018-02-02 14:09:43

标签: python pandas datetime

我想以月为间隔创建给定数量日期的列表(或数组或其中)。

基本上我想要的是这个

>>>some_function(start_date=date(2005, 5, 14), periods=4, freq='M')
['2005-05-14', '2005-06-14', '2005-07-14', '2005-08-14']

如果startmonth的那天接近月末我想要这个

>>>some_function(start_date=date(2007, 12, 31), periods=4, freq='M')
['2007-12-31', '2008-01-31', '2008-02-29', '2008-03-31']

我知道pandas date_range函数,但它产生了这个

pd.date_range(date(2005, 5, 14), periods=4, freq='M')
Out[1]: DatetimeIndex(['2005-05-31', '2005-06-30', '2005-07-31', '2005-08-31'],
          dtype='datetime64[ns]', freq='M')

即。它将月末设为日。这不是我想要的。

显然,这可以在句点数量上迭代生成,但是当startmonth的日期接近该月的最后一天时,这会产生麻烦。

是否有人知道产生此功能的功能或上述方法是唯一的方法?

3 个答案:

答案 0 :(得分:2)

这应该有效。 add_months函数来自How to increment datetime by custom months in python without using library中的@DaveWebb。

import datetime
import calendar

start_date = '2018-02-02'

def add_months(sourcedate, months):
    month = sourcedate.month - 1 + months
    year = sourcedate.year + month // 12
    month = month % 12 + 1
    day = min(sourcedate.day, calendar.monthrange(year, month)[1])
    return datetime.date(year, month, day)

def range_of_months(sourcedate, months):
    return [add_months(sourcedate, m) for m in range(months+1)]

start = datetime.date.today()

range_of_months(start, 5)

# [datetime.date(2018, 2, 2),
#  datetime.date(2018, 3, 2),
#  datetime.date(2018, 4, 2),
#  datetime.date(2018, 5, 2),
#  datetime.date(2018, 6, 2),
#  datetime.date(2018, 7, 2)]

答案 1 :(得分:2)

我精心设计了以下内容:

public class SortingDialog extends DialogFragment {

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Create a builder to make the dialog building process easier
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle("Sorting Dialog");
    builder.setSingleChoiceItems(R.array.sorting_options, 0,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    if (i == 1) {
                        Toast.makeText(getActivity(), "2nd option Clicked", Toast.LENGTH_SHORT).show();
                        if (getActivity().getSupportFragmentManager().findFragmentByTag("GLOBAL_FRAGMENT") != null) {
                            sortGlobalListsBasedOnNameAndDesc();
                        }
                    }
                    for (int j = 0; j < GlobalDataHolder.cardNameAndDescription.size(); j++) {
                        Log.v("card_names", GlobalDataHolder.cardNameAndDescription.get(j));
                    }
                }
            });
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            createToast();
            dismiss();
        }
    });
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            dismiss();
        }
    });
    return builder.create();
}

private void sortGlobalListsBasedOnNameAndDesc() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        GlobalDataHolder.cardNameAndDescription.sort(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int id1 = GlobalDataHolder.cardNameAndDescription.indexOf(s1);
                int id2 = GlobalDataHolder.cardNameAndDescription.indexOf(s2);

                if (s1.equals(s2)) {
                    return 0;
                } else if (s1.compareToIgnoreCase(s2) > 0) { //s1 is greater
                    //Collections.swap(UserBoxGlbImageAdapter.mGLBIcons,id2,id1);
                    swap(UserBoxGlbImageAdapter.mGLBIcons,id2,id1);
                    swap(GlobalDataHolder.cardNameAndDescription,id2,id1);
                    Log.d("case1","Called 1 time");
                    return 1;
                } else if (s1.compareToIgnoreCase(s2) < 0) { //s1 is smaller
                    //Collections.swap(UserBoxGlbImageAdapter.mGLBIcons,id1,id2);
                    swap(UserBoxGlbImageAdapter.mGLBIcons,id1,id2);
                    swap(GlobalDataHolder.cardNameAndDescription,id1,id2);
                    Log.d("case2","Called 1 time");
                    return -1;
                } else {
                    return 0;
                }
            }
        });
    }
}

private void swap(List list,int objIndex1, int objIndex2) {
    for (int i=0;i < list.size(); i++) {
        Collections.swap(list,objIndex1,objIndex2);
        UserBoxGlbImageAdapter.refreshFragmentView(UserBoxGLBFragment.getUserBoxAdapter());
    }
}

private void createToast() {
    Toast.makeText(getActivity(), "Cards sorted based on AVG Stats", Toast.LENGTH_SHORT).show();
}
}

答案 2 :(得分:1)

我认为您要遵循的行为是,您想要一个日期范围,其中所有日期都与开始日期在月份的同一天,但在月份中使用较少的月份使用月份的最后一天这个月。

您可以通过使用pandas.DateOffset(months=1, day=day_of_month)作为freq参数来实现,其中day_of_month是您希望每个日期都开启的月份。这将自动使用月份的最后一天少于最后一天少于day_of_month的月份。

In [68]: pandas.date_range('2005-05-14', periods=4, freq=pandas.DateOffset(months=1, day=14))
Out[68]: DatetimeIndex(['2005-05-14', '2005-06-14', '2005-07-14', '2005-08-14'], dtype='datetime64[ns]', freq='<DateOffset: day=14, months=1>')

In [69]: pandas.date_range('2007-12-31', periods=4, freq=pandas.DateOffset(months=1, day=31))
Out[69]: DatetimeIndex(['2007-12-31', '2008-01-31', '2008-02-29', '2008-03-31'], dtype='datetime64[ns]', freq='<DateOffset: day=31, months=1>')