日付処理
後で書きます(ぺこり)
日付型・日付文字列型・UnixTime整数型 相互変換
日付のイテレート
データが年月日別に管理され、その中から期間を指定して分析を行いたいことはよくある。
期間を文字列で指定すると、1日ずつ順番に日付を返すジェネレータがあると便利。
主な使い方
- 入力文字列
<Dates>
- 指定方法
<Date> ::= “YYYYMMDD”
形式の日付文字列<Dates>::= <Date> | <Date>-<Date> | <Dates>,<Dates>
- 意味
- ハイフン区切り「
YYYYMMDD-YYYYMMDD
」は、期間を表す - カンマ区切り「
YYYYMMDD,YYYYMMDD
」は、別々の2日を表す
- 返値
YYYYMMDD
の文字列を指定された順に返すIterator
(例) 入力: 20150101-20150331,20150701,20150801 出力: 20150101, 20150102, 20150103, ..., 20150331, 20150701, 20150801
from datetime import datetime from dateutil.relativedelta import relativedelta # 日単位でのイテレート ------------------------------------ # 補助関数 def _generate_between_date(start_date_str, stop_date_str): start_date = datetime.strptime(start_date_str, '%Y%m%d') stop_date = datetime.strptime(stop_date_str, '%Y%m%d') while start_date <= stop_date: yield start_date.strftime('%Y%m%d') start_date += relativedelta(days=1) # こちらを使う def date_sequence_generator(dates_str): for date_str in dates_str.split(','): if '-' in date_str: for date in _generate_between_date(*date_str.split('-')): yield date else: yield date_str # 月単位でのイテレート ----------------------------------- def _generate_between_month(start_month_str, stop_month_str): start_month = datetime.strptime(start_month_str, '%Y%m') stop_month = datetime.strptime(stop_month_str, '%Y%m') while start_month <= stop_month: yield start_month.strftime('%Y%m') start_month += relativedelta(months=1) def month_sequence_generator(months_str): for month_str in months_str.split(','): if '-' in month_str: for month in _generate_between_month(*month_str.split('-')): yield month else: yield month_str
use DateTime; class DateIterator { function iterateDate($target_dates) { $comma_explodeds = explode(',', $target_dates); foreach ($comma_explodeds as $cma) { $hyphen_explodeds = explode('-', $cma); if (count($hyphen_explodeds) === 1) { yield $cma; } elseif (count($hyphen_explodeds) === 2) { $d = DateTime::createFromFormat( 'Ymd', $hyphen_explodeds[0]); $t = DateTime::createFromFormat( 'Ymd', $hyphen_explodeds[1]); if ($d === false || $t === false) { throw new \UnexpectedValueException( 'iterateDate parse date'); } while ($d <= $t) { yield $d->format('Ymd'); $d->modify('+1 day'); } } else { throw new \UnexpectedValueException( 'iterateDate hyphen'); } } } }
KotlinではGeneratorの機能がまだexperimentalなので、Listを返すようにする。
また、Java8より導入されたLocalDateTimeを利用する。
import java.time.LocalDate import java.time.format.DateTimeFormatter import java.time.format.ResolverStyle fun String.iterateDate(): List<String> { val formatter = DateTimeFormatter.ofPattern("uuuuMMdd").withResolverStyle(ResolverStyle.STRICT) val dateList = mutableListOf<String>() this.split(',').forEach { val hyphenSplit = it.split('-') when (hyphenSplit.size) { 1 -> { // パースできるかだけ確認 LocalDate.parse(hyphenSplit[0], formatter) dateList += hyphenSplit[0] } 2 -> { var curDate = LocalDate.parse(hyphenSplit[0], formatter) val tgtDate = LocalDate.parse(hyphenSplit[1], formatter) while (curDate <= tgtDate) { dateList += curDate.format(formatter) curDate = curDate.plusDays(1) } } else -> { throw IllegalArgumentException("Can't iterate date: %s".format(it)) } } } return dateList }