mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
some review fixes and add new function toStartOfWeek
This commit is contained in:
parent
ec9a97d499
commit
6085fce8d7
@ -35,35 +35,53 @@ struct ZeroTransform
|
||||
static inline UInt16 execute(UInt16, UInt8, const DateLUTImpl &) { return 0; }
|
||||
};
|
||||
|
||||
struct WeekImpl
|
||||
struct ToWeekImpl
|
||||
{
|
||||
static constexpr auto name = "week";
|
||||
static constexpr auto name = "toWeek";
|
||||
|
||||
static inline UInt8 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
UInt32 year = 0;
|
||||
return time_zone.calc_week(time_zone.toDayNum(t), week_mode, &year);
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
static inline UInt8 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
UInt32 year = 0;
|
||||
return time_zone.calc_week(DayNum(d), week_mode, &year);
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode);
|
||||
return yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct YearWeekImpl
|
||||
struct ToYearWeekImpl
|
||||
{
|
||||
static constexpr auto name = "yearWeek";
|
||||
static constexpr auto name = "toYearWeek";
|
||||
|
||||
static inline UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.calc_yearWeek(time_zone.toDayNum(t), week_mode);
|
||||
YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
static inline UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.calc_yearWeek(DayNum(d), week_mode);
|
||||
YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast<UInt32>(WeekModeFlag::YEAR));
|
||||
return yw.first * 100 + yw.second;
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToStartOfWeekImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfWeek";
|
||||
|
||||
static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode);
|
||||
}
|
||||
static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode);
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
|
@ -7,13 +7,19 @@
|
||||
|
||||
namespace DB
|
||||
{
|
||||
using FunctionWeek = FunctionCustomWeekToSomething<DataTypeUInt8, WeekImpl>;
|
||||
using FunctionYearWeek = FunctionCustomWeekToSomething<DataTypeUInt32, YearWeekImpl>;
|
||||
using FunctionToWeek = FunctionCustomWeekToSomething<DataTypeUInt8, ToWeekImpl>;
|
||||
using FunctionToYearWeek = FunctionCustomWeekToSomething<DataTypeUInt32, ToYearWeekImpl>;
|
||||
using FunctionToStartOfWeek = FunctionCustomWeekToSomething<DataTypeDate, ToStartOfWeekImpl>;
|
||||
|
||||
void registerFunctionToCustomWeek(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionWeek>();
|
||||
factory.registerFunction<FunctionYearWeek>();
|
||||
factory.registerFunction<FunctionToWeek>();
|
||||
factory.registerFunction<FunctionToYearWeek>();
|
||||
factory.registerFunction<FunctionToStartOfWeek>();
|
||||
|
||||
/// Compatibility aliases for mysql.
|
||||
factory.registerAlias("week", "toWeek", FunctionFactory::CaseInsensitive);
|
||||
factory.registerAlias("yearweek", "toYearWeek", FunctionFactory::CaseInsensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -61,3 +61,13 @@
|
||||
2017-01-09 00:00:00 2 3 201702 201703
|
||||
2017-01-10 00:00:00 2 3 201702 201703
|
||||
2017-01-11 00:00:00 2 3 201702 201703
|
||||
2018-12-25 2018-12-25 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24
|
||||
2018-12-26 2018-12-26 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24
|
||||
2018-12-27 2018-12-27 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24
|
||||
2018-12-28 2018-12-28 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24
|
||||
2018-12-29 2018-12-29 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24
|
||||
2018-12-30 2018-12-30 00:00:00 2018-12-30 2018-12-30 2018-12-24 2018-12-24
|
||||
2018-12-31 2018-12-31 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31
|
||||
2019-01-01 2019-01-01 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31
|
||||
2019-01-02 2019-01-02 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31
|
||||
2019-01-03 2019-01-03 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31
|
||||
|
@ -1,42 +1,52 @@
|
||||
-- week mode [0,7], week test case. refer to the mysql test case
|
||||
SELECT week(toDate('1998-01-01')), week(toDate('1997-01-01')), week(toDate('1998-01-01'), 1), week(toDate('1997-01-01'), 1);
|
||||
SELECT week(toDate('1998-12-31')), week(toDate('1997-12-31')), week(toDate('1998-12-31'), 1), week(toDate('1997-12-31'), 1);
|
||||
SELECT week(toDate('1995-01-01')), week(toDate('1995-01-01'), 1);
|
||||
SELECT yearWeek(toDate('1981-12-31'), 1), yearWeek(toDate('1982-01-01'), 1), yearWeek(toDate('1982-12-31'), 1), yearWeek(toDate('1983-01-01'), 1);
|
||||
SELECT yearWeek(toDate('1987-01-01'), 1), yearWeek(toDate('1987-01-01'));
|
||||
SELECT toWeek(toDate('1998-01-01')), toWeek(toDate('1997-01-01')), toWeek(toDate('1998-01-01'), 1), toWeek(toDate('1997-01-01'), 1);
|
||||
SELECT toWeek(toDate('1998-12-31')), toWeek(toDate('1997-12-31')), toWeek(toDate('1998-12-31'), 1), toWeek(toDate('1997-12-31'), 1);
|
||||
SELECT toWeek(toDate('1995-01-01')), toWeek(toDate('1995-01-01'), 1);
|
||||
SELECT toYearWeek(toDate('1981-12-31'), 1), toYearWeek(toDate('1982-01-01'), 1), toYearWeek(toDate('1982-12-31'), 1), toYearWeek(toDate('1983-01-01'), 1);
|
||||
SELECT toYearWeek(toDate('1987-01-01'), 1), toYearWeek(toDate('1987-01-01'));
|
||||
|
||||
SELECT week(toDate('2000-01-01'),0) AS w2000, week(toDate('2001-01-01'),0) AS w2001, week(toDate('2002-01-01'),0) AS w2002,week(toDate('2003-01-01'),0) AS w2003, week(toDate('2004-01-01'),0) AS w2004, week(toDate('2005-01-01'),0) AS w2005, week(toDate('2006-01-01'),0) AS w2006;
|
||||
SELECT week(toDate('2000-01-06'),0) AS w2000, week(toDate('2001-01-06'),0) AS w2001, week(toDate('2002-01-06'),0) AS w2002,week(toDate('2003-01-06'),0) AS w2003, week(toDate('2004-01-06'),0) AS w2004, week(toDate('2005-01-06'),0) AS w2005, week(toDate('2006-01-06'),0) AS w2006;
|
||||
SELECT week(toDate('2000-01-01'),1) AS w2000, week(toDate('2001-01-01'),1) AS w2001, week(toDate('2002-01-01'),1) AS w2002,week(toDate('2003-01-01'),1) AS w2003, week(toDate('2004-01-01'),1) AS w2004, week(toDate('2005-01-01'),1) AS w2005, week(toDate('2006-01-01'),1) AS w2006;
|
||||
SELECT week(toDate('2000-01-06'),1) AS w2000, week(toDate('2001-01-06'),1) AS w2001, week(toDate('2002-01-06'),1) AS w2002,week(toDate('2003-01-06'),1) AS w2003, week(toDate('2004-01-06'),1) AS w2004, week(toDate('2005-01-06'),1) AS w2005, week(toDate('2006-01-06'),1) AS w2006;
|
||||
SELECT yearWeek(toDate('2000-01-01'),0) AS w2000, yearWeek(toDate('2001-01-01'),0) AS w2001, yearWeek(toDate('2002-01-01'),0) AS w2002,yearWeek(toDate('2003-01-01'),0) AS w2003, yearWeek(toDate('2004-01-01'),0) AS w2004, yearWeek(toDate('2005-01-01'),0) AS w2005, yearWeek(toDate('2006-01-01'),0) AS w2006;
|
||||
SELECT yearWeek(toDate('2000-01-06'),0) AS w2000, yearWeek(toDate('2001-01-06'),0) AS w2001, yearWeek(toDate('2002-01-06'),0) AS w2002,yearWeek(toDate('2003-01-06'),0) AS w2003, yearWeek(toDate('2004-01-06'),0) AS w2004, yearWeek(toDate('2005-01-06'),0) AS w2005, yearWeek(toDate('2006-01-06'),0) AS w2006;
|
||||
SELECT yearWeek(toDate('2000-01-01'),1) AS w2000, yearWeek(toDate('2001-01-01'),1) AS w2001, yearWeek(toDate('2002-01-01'),1) AS w2002,yearWeek(toDate('2003-01-01'),1) AS w2003, yearWeek(toDate('2004-01-01'),1) AS w2004, yearWeek(toDate('2005-01-01'),1) AS w2005, yearWeek(toDate('2006-01-01'),1) AS w2006;
|
||||
SELECT yearWeek(toDate('2000-01-06'),1) AS w2000, yearWeek(toDate('2001-01-06'),1) AS w2001, yearWeek(toDate('2002-01-06'),1) AS w2002,yearWeek(toDate('2003-01-06'),1) AS w2003, yearWeek(toDate('2004-01-06'),1) AS w2004, yearWeek(toDate('2005-01-06'),1) AS w2005, yearWeek(toDate('2006-01-06'),1) AS w2006;
|
||||
SELECT week(toDate('1998-12-31'),2),week(toDate('1998-12-31'),3), week(toDate('2000-01-01'),2), week(toDate('2000-01-01'),3);
|
||||
SELECT week(toDate('2000-12-31'),2),week(toDate('2000-12-31'),3);
|
||||
SELECT toWeek(toDate('2000-01-01'),0) AS w2000, toWeek(toDate('2001-01-01'),0) AS w2001, toWeek(toDate('2002-01-01'),0) AS w2002,toWeek(toDate('2003-01-01'),0) AS w2003, toWeek(toDate('2004-01-01'),0) AS w2004, toWeek(toDate('2005-01-01'),0) AS w2005, toWeek(toDate('2006-01-01'),0) AS w2006;
|
||||
SELECT toWeek(toDate('2000-01-06'),0) AS w2000, toWeek(toDate('2001-01-06'),0) AS w2001, toWeek(toDate('2002-01-06'),0) AS w2002,toWeek(toDate('2003-01-06'),0) AS w2003, toWeek(toDate('2004-01-06'),0) AS w2004, toWeek(toDate('2005-01-06'),0) AS w2005, toWeek(toDate('2006-01-06'),0) AS w2006;
|
||||
SELECT toWeek(toDate('2000-01-01'),1) AS w2000, toWeek(toDate('2001-01-01'),1) AS w2001, toWeek(toDate('2002-01-01'),1) AS w2002,toWeek(toDate('2003-01-01'),1) AS w2003, toWeek(toDate('2004-01-01'),1) AS w2004, toWeek(toDate('2005-01-01'),1) AS w2005, toWeek(toDate('2006-01-01'),1) AS w2006;
|
||||
SELECT toWeek(toDate('2000-01-06'),1) AS w2000, toWeek(toDate('2001-01-06'),1) AS w2001, toWeek(toDate('2002-01-06'),1) AS w2002,toWeek(toDate('2003-01-06'),1) AS w2003, toWeek(toDate('2004-01-06'),1) AS w2004, toWeek(toDate('2005-01-06'),1) AS w2005, toWeek(toDate('2006-01-06'),1) AS w2006;
|
||||
SELECT toYearWeek(toDate('2000-01-01'),0) AS w2000, toYearWeek(toDate('2001-01-01'),0) AS w2001, toYearWeek(toDate('2002-01-01'),0) AS w2002,toYearWeek(toDate('2003-01-01'),0) AS w2003, toYearWeek(toDate('2004-01-01'),0) AS w2004, toYearWeek(toDate('2005-01-01'),0) AS w2005, toYearWeek(toDate('2006-01-01'),0) AS w2006;
|
||||
SELECT toYearWeek(toDate('2000-01-06'),0) AS w2000, toYearWeek(toDate('2001-01-06'),0) AS w2001, toYearWeek(toDate('2002-01-06'),0) AS w2002,toYearWeek(toDate('2003-01-06'),0) AS w2003, toYearWeek(toDate('2004-01-06'),0) AS w2004, toYearWeek(toDate('2005-01-06'),0) AS w2005, toYearWeek(toDate('2006-01-06'),0) AS w2006;
|
||||
SELECT toYearWeek(toDate('2000-01-01'),1) AS w2000, toYearWeek(toDate('2001-01-01'),1) AS w2001, toYearWeek(toDate('2002-01-01'),1) AS w2002,toYearWeek(toDate('2003-01-01'),1) AS w2003, toYearWeek(toDate('2004-01-01'),1) AS w2004, toYearWeek(toDate('2005-01-01'),1) AS w2005, toYearWeek(toDate('2006-01-01'),1) AS w2006;
|
||||
SELECT toYearWeek(toDate('2000-01-06'),1) AS w2000, toYearWeek(toDate('2001-01-06'),1) AS w2001, toYearWeek(toDate('2002-01-06'),1) AS w2002,toYearWeek(toDate('2003-01-06'),1) AS w2003, toYearWeek(toDate('2004-01-06'),1) AS w2004, toYearWeek(toDate('2005-01-06'),1) AS w2005, toYearWeek(toDate('2006-01-06'),1) AS w2006;
|
||||
SELECT toWeek(toDate('1998-12-31'),2),toWeek(toDate('1998-12-31'),3), toWeek(toDate('2000-01-01'),2), toWeek(toDate('2000-01-01'),3);
|
||||
SELECT toWeek(toDate('2000-12-31'),2),toWeek(toDate('2000-12-31'),3);
|
||||
|
||||
SELECT week(toDate('1998-12-31'),0) AS w0, week(toDate('1998-12-31'),1) AS w1, week(toDate('1998-12-31'),2) AS w2, week(toDate('1998-12-31'),3) AS w3, week(toDate('1998-12-31'),4) AS w4, week(toDate('1998-12-31'),5) AS w5, week(toDate('1998-12-31'),6) AS w6, week(toDate('1998-12-31'),7) AS w7;
|
||||
SELECT week(toDate('2000-01-01'),0) AS w0, week(toDate('2000-01-01'),1) AS w1, week(toDate('2000-01-01'),2) AS w2, week(toDate('2000-01-01'),3) AS w3, week(toDate('2000-01-01'),4) AS w4, week(toDate('2000-01-01'),5) AS w5, week(toDate('2000-01-01'),6) AS w6, week(toDate('2000-01-01'),7) AS w7;
|
||||
SELECT week(toDate('2000-01-06'),0) AS w0, week(toDate('2000-01-06'),1) AS w1, week(toDate('2000-01-06'),2) AS w2, week(toDate('2000-01-06'),3) AS w3, week(toDate('2000-01-06'),4) AS w4, week(toDate('2000-01-06'),5) AS w5, week(toDate('2000-01-06'),6) AS w6, week(toDate('2000-01-06'),7) AS w7;
|
||||
SELECT week(toDate('2000-12-31'),0) AS w0, week(toDate('2000-12-31'),1) AS w1, week(toDate('2000-12-31'),2) AS w2, week(toDate('2000-12-31'),3) AS w3, week(toDate('2000-12-31'),4) AS w4, week(toDate('2000-12-31'),5) AS w5, week(toDate('2000-12-31'),6) AS w6, week(toDate('2000-12-31'),7) AS w7;
|
||||
SELECT week(toDate('2001-01-01'),0) AS w0, week(toDate('2001-01-01'),1) AS w1, week(toDate('2001-01-01'),2) AS w2, week(toDate('2001-01-01'),3) AS w3, week(toDate('2001-01-01'),4) AS w4, week(toDate('2001-01-01'),5) AS w5, week(toDate('2001-01-01'),6) AS w6, week(toDate('2001-01-01'),7) AS w7;
|
||||
SELECT toWeek(toDate('1998-12-31'),0) AS w0, toWeek(toDate('1998-12-31'),1) AS w1, toWeek(toDate('1998-12-31'),2) AS w2, toWeek(toDate('1998-12-31'),3) AS w3, toWeek(toDate('1998-12-31'),4) AS w4, toWeek(toDate('1998-12-31'),5) AS w5, toWeek(toDate('1998-12-31'),6) AS w6, toWeek(toDate('1998-12-31'),7) AS w7;
|
||||
SELECT toWeek(toDate('2000-01-01'),0) AS w0, toWeek(toDate('2000-01-01'),1) AS w1, toWeek(toDate('2000-01-01'),2) AS w2, toWeek(toDate('2000-01-01'),3) AS w3, toWeek(toDate('2000-01-01'),4) AS w4, toWeek(toDate('2000-01-01'),5) AS w5, toWeek(toDate('2000-01-01'),6) AS w6, toWeek(toDate('2000-01-01'),7) AS w7;
|
||||
SELECT toWeek(toDate('2000-01-06'),0) AS w0, toWeek(toDate('2000-01-06'),1) AS w1, toWeek(toDate('2000-01-06'),2) AS w2, toWeek(toDate('2000-01-06'),3) AS w3, toWeek(toDate('2000-01-06'),4) AS w4, toWeek(toDate('2000-01-06'),5) AS w5, toWeek(toDate('2000-01-06'),6) AS w6, toWeek(toDate('2000-01-06'),7) AS w7;
|
||||
SELECT toWeek(toDate('2000-12-31'),0) AS w0, toWeek(toDate('2000-12-31'),1) AS w1, toWeek(toDate('2000-12-31'),2) AS w2, toWeek(toDate('2000-12-31'),3) AS w3, toWeek(toDate('2000-12-31'),4) AS w4, toWeek(toDate('2000-12-31'),5) AS w5, toWeek(toDate('2000-12-31'),6) AS w6, toWeek(toDate('2000-12-31'),7) AS w7;
|
||||
SELECT toWeek(toDate('2001-01-01'),0) AS w0, toWeek(toDate('2001-01-01'),1) AS w1, toWeek(toDate('2001-01-01'),2) AS w2, toWeek(toDate('2001-01-01'),3) AS w3, toWeek(toDate('2001-01-01'),4) AS w4, toWeek(toDate('2001-01-01'),5) AS w5, toWeek(toDate('2001-01-01'),6) AS w6, toWeek(toDate('2001-01-01'),7) AS w7;
|
||||
|
||||
SELECT yearWeek(toDate('2000-12-31'),0), yearWeek(toDate('2000-12-31'),1), yearWeek(toDate('2000-12-31'),2), yearWeek(toDate('2000-12-31'),3), yearWeek(toDate('2000-12-31'),4), yearWeek(toDate('2000-12-31'),5), yearWeek(toDate('2000-12-31'),6), yearWeek(toDate('2000-12-31'),7);
|
||||
SELECT toYearWeek(toDate('2000-12-31'),0), toYearWeek(toDate('2000-12-31'),1), toYearWeek(toDate('2000-12-31'),2), toYearWeek(toDate('2000-12-31'),3), toYearWeek(toDate('2000-12-31'),4), toYearWeek(toDate('2000-12-31'),5), toYearWeek(toDate('2000-12-31'),6), toYearWeek(toDate('2000-12-31'),7);
|
||||
|
||||
-- week mode 8,9
|
||||
SELECT
|
||||
toDate('2016-12-21') + number AS d,
|
||||
week(d, 8) AS week8,
|
||||
week(d, 9) AS week9,
|
||||
yearWeek(d, 8) AS yearWeek8,
|
||||
yearWeek(d, 9) AS yearWeek9
|
||||
toWeek(d, 8) AS week8,
|
||||
toWeek(d, 9) AS week9,
|
||||
toYearWeek(d, 8) AS yearWeek8,
|
||||
toYearWeek(d, 9) AS yearWeek9
|
||||
FROM numbers(21);
|
||||
|
||||
SELECT toDateTime(toDate('2016-12-22') + number, 'Europe/Moscow' ) AS d,
|
||||
week(d, 8, 'Europe/Moscow') AS week8,
|
||||
week(d, 9, 'Europe/Moscow') AS week9,
|
||||
yearWeek(d, 8, 'Europe/Moscow') AS yearWeek8,
|
||||
yearWeek(d, 9, 'Europe/Moscow') AS yearWeek9
|
||||
toWeek(d, 8, 'Europe/Moscow') AS week8,
|
||||
toWeek(d, 9, 'Europe/Moscow') AS week9,
|
||||
toYearWeek(d, 8, 'Europe/Moscow') AS yearWeek8,
|
||||
toYearWeek(d, 9, 'Europe/Moscow') AS yearWeek9
|
||||
FROM numbers(21);
|
||||
|
||||
-- toStartOfWeek
|
||||
SELECT
|
||||
toDate('2018-12-25') + number AS x,
|
||||
toDateTime(x) AS x_t,
|
||||
toStartOfWeek(x) AS w0,
|
||||
toStartOfWeek(x_t) AS wt0,
|
||||
toStartOfWeek(x, 3) AS w3,
|
||||
toStartOfWeek(x_t, 3) AS wt3
|
||||
FROM numbers(10);
|
||||
|
||||
|
@ -95,6 +95,12 @@ Returns the date.
|
||||
Rounds down a date or date with time to the nearest Monday.
|
||||
Returns the date.
|
||||
|
||||
## toStartOfWeek(t[,mode])
|
||||
|
||||
Rounds down a date or date with time to the nearest Sunday or Monday by mode.
|
||||
Returns the date.
|
||||
The mode argument works exactly like the mode argument to toWeek(). For the single-argument syntax, a mode value of 0 is used.
|
||||
|
||||
## toStartOfDay
|
||||
|
||||
Rounds down a date with time to the start of the day.
|
||||
@ -169,9 +175,9 @@ Converts a date or date with time to a UInt16 number containing the ISO Year num
|
||||
|
||||
Converts a date or date with time to a UInt8 number containing the ISO Week number.
|
||||
|
||||
## week(date[,mode])
|
||||
This function returns the week number for date or datetime. The two-argument form of week() enables you to specify whether the week starts on Sunday or Monday and whether the return value should be in the range from 0 to 53 or from 1 to 53. If the mode argument is omitted, the default mode is 0.
|
||||
`toISOWeek() `is a compatibility function that is equivalent to `week(date,3)`.
|
||||
## toWeek(date[,mode])
|
||||
This function returns the week number for date or datetime. The two-argument form of toWeek() enables you to specify whether the week starts on Sunday or Monday and whether the return value should be in the range from 0 to 53 or from 1 to 53. If the mode argument is omitted, the default mode is 0.
|
||||
`toISOWeek() `is a compatibility function that is equivalent to `toWeek(date,3)`.
|
||||
The following table describes how the mode argument works.
|
||||
|
||||
| Mode | First day of week | Range | Week 1 is the first week … |
|
||||
@ -196,7 +202,7 @@ For mode values with a meaning of “with 4 or more days this year,” weeks are
|
||||
For mode values with a meaning of “contains January 1”, the week contains January 1 is week 1. It doesn't matter how many days in the new year the week contained, even if it contained only one day.
|
||||
|
||||
```
|
||||
week(date, [, mode][, Timezone])
|
||||
toWeek(date, [, mode][, Timezone])
|
||||
```
|
||||
**Parameters**
|
||||
|
||||
@ -207,7 +213,7 @@ week(date, [, mode][, Timezone])
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT toDate('2016-12-27') AS date, week(date) AS week0, week(date,1) AS week1, week(date,9) AS week9;
|
||||
SELECT toDate('2016-12-27') AS date, toWeek(date) AS week0, toWeek(date,1) AS week1, toWeek(date,9) AS week9;
|
||||
```
|
||||
|
||||
```
|
||||
@ -216,17 +222,17 @@ SELECT toDate('2016-12-27') AS date, week(date) AS week0, week(date,1) AS week1,
|
||||
└────────────┴───────┴───────┴───────┘
|
||||
```
|
||||
|
||||
## yearWeek(date[,mode])
|
||||
## toYearWeek(date[,mode])
|
||||
Returns year and week for a date. The year in the result may be different from the year in the date argument for the first and the last week of the year.
|
||||
|
||||
The mode argument works exactly like the mode argument to week(). For the single-argument syntax, a mode value of 0 is used.
|
||||
The mode argument works exactly like the mode argument to toWeek(). For the single-argument syntax, a mode value of 0 is used.
|
||||
|
||||
`toISOYear() `is a compatibility function that is equivalent to `intDiv(yearWeek(date,3),100)`.
|
||||
`toISOYear() `is a compatibility function that is equivalent to `intDiv(toYearWeek(date,3),100)`.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT toDate('2016-12-27') AS date, yearWeek(date) AS yearWeek0, yearWeek(date,1) AS yearWeek1, yearWeek(date,9) AS yearWeek9;
|
||||
SELECT toDate('2016-12-27') AS date, toYearWeek(date) AS yearWeek0, toYearWeek(date,1) AS yearWeek1, toYearWeek(date,9) AS yearWeek9;
|
||||
```
|
||||
|
||||
```
|
||||
|
@ -14,18 +14,21 @@
|
||||
#define DATE_LUT_MAX_YEAR 2105 /// Last supported year
|
||||
#define DATE_LUT_YEARS (1 + DATE_LUT_MAX_YEAR - DATE_LUT_MIN_YEAR) /// Number of years in lookup table
|
||||
|
||||
/// Flags for calc_week() function.
|
||||
#define WEEK_MONDAY_FIRST 1
|
||||
#define WEEK_YEAR 2
|
||||
#define WEEK_FIRST_WEEKDAY 4
|
||||
#define WEEK_NEWYEAR_DAY 8
|
||||
|
||||
|
||||
#if defined(__PPC__)
|
||||
# if !__clang__
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
# endif
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Flags for toYearWeek() function.
|
||||
enum class WeekModeFlag : UInt8
|
||||
{
|
||||
MONDAY_FIRST = 1,
|
||||
YEAR = 2,
|
||||
FIRST_WEEKDAY = 4,
|
||||
NEWYEAR_DAY = 8
|
||||
};
|
||||
typedef std::pair<UInt16, UInt8> YearWeek;
|
||||
|
||||
/** Lookup table to conversion of time to date, and to month / year / day of week / day of month and so on.
|
||||
* First time was implemented for OLAPServer, that needed to do billions of such transformations.
|
||||
@ -330,15 +333,15 @@ public:
|
||||
|
||||
/*
|
||||
The bits in week_mode has the following meaning:
|
||||
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
|
||||
WeekModeFlag::MONDAY_FIRST (0) If not set Sunday is first day of week
|
||||
If set Monday is first day of week
|
||||
WEEK_YEAR (1) If not set Week is in range 0-53
|
||||
WeekModeFlag::YEAR (1) If not set Week is in range 0-53
|
||||
|
||||
Week 0 is returned for the the last week of the previous year (for
|
||||
a date at start of january) In this case one can get 53 for the
|
||||
first week of next year. This flag ensures that the week is
|
||||
relevant for the given year. Note that this flag is only
|
||||
releveant if WEEK_JANUARY is not set.
|
||||
releveant if WeekModeFlag::JANUARY is not set.
|
||||
|
||||
If set Week is in range 1-53.
|
||||
|
||||
@ -346,52 +349,51 @@ public:
|
||||
the week is that last week of previous year) and week 1 for a
|
||||
date in December.
|
||||
|
||||
WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
|
||||
WeekModeFlag::FIRST_WEEKDAY (2) If not set Weeks are numbered according
|
||||
to ISO 8601:1988
|
||||
If set The week that contains the first
|
||||
'first-day-of-week' is week 1.
|
||||
|
||||
WEEK_NEWYEAR_DAY (3)
|
||||
WeekModeFlag::NEWYEAR_DAY (3)
|
||||
If set The week that contains the January 1 is week 1.
|
||||
Week is in range 1-53.
|
||||
And ignore WEEK_YEAR, WEEK_FIRST_WEEKDAY
|
||||
And ignore WeekModeFlag::YEAR, WeekModeFlag::FIRST_WEEKDAY
|
||||
|
||||
ISO 8601:1988 means that if the week containing January 1 has
|
||||
four or more days in the new year, then it is week 1;
|
||||
Otherwise it is the last week of the previous year, and the
|
||||
next week is week 1.
|
||||
*/
|
||||
inline unsigned calc_week(DayNum d, UInt32 week_mode, UInt32 * year) const
|
||||
inline YearWeek toYearWeek(DayNum d, UInt8 week_mode) const
|
||||
{
|
||||
bool newyear_day_mode = week_mode & WEEK_NEWYEAR_DAY;
|
||||
|
||||
bool newyear_day_mode = week_mode & static_cast<UInt8>(WeekModeFlag::NEWYEAR_DAY);
|
||||
week_mode = check_week_mode(week_mode);
|
||||
bool monday_first_mode = week_mode & WEEK_MONDAY_FIRST;
|
||||
bool week_year_mode = week_mode & WEEK_YEAR;
|
||||
bool first_weekday_mode = week_mode & WEEK_FIRST_WEEKDAY;
|
||||
bool monday_first_mode = week_mode & static_cast<UInt8>(WeekModeFlag::MONDAY_FIRST);
|
||||
bool week_year_mode = week_mode & static_cast<UInt8>(WeekModeFlag::YEAR);
|
||||
bool first_weekday_mode = week_mode & static_cast<UInt8>(WeekModeFlag::FIRST_WEEKDAY);
|
||||
|
||||
// Calculate week number of WEEK_NEWYEAR_DAY mode
|
||||
// Calculate week number of WeekModeFlag::NEWYEAR_DAY mode
|
||||
if (newyear_day_mode)
|
||||
{
|
||||
return calc_newyear_week(d, monday_first_mode, year);
|
||||
return toYearWeekOfNewyearMode(d, monday_first_mode);
|
||||
}
|
||||
|
||||
UInt32 days = 0;
|
||||
UInt64 daynr = calc_daynr(toYear(d), toMonth(d), toDayOfMonth(d));
|
||||
UInt64 first_daynr = calc_daynr(toYear(d), 1, 1);
|
||||
YearWeek yw(toYear(d), 0);
|
||||
UInt16 days = 0;
|
||||
UInt16 daynr = makeDayNum(yw.first, toMonth(d), toDayOfMonth(d));
|
||||
UInt16 first_daynr = makeDayNum(yw.first, 1, 1);
|
||||
|
||||
// 0 for monday, 1 for tuesday ...
|
||||
// get weekday from first day in year.
|
||||
UInt32 weekday = calc_weekday(first_daynr, !monday_first_mode);
|
||||
*year = toYear(d);
|
||||
UInt16 weekday = calc_weekday(DayNum(first_daynr), !monday_first_mode);
|
||||
|
||||
if (toMonth(d) == 1 && toDayOfMonth(d) <= 7 - weekday)
|
||||
{
|
||||
if (!week_year_mode && ((first_weekday_mode && weekday != 0) || (!first_weekday_mode && weekday >= 4)))
|
||||
return 0;
|
||||
return yw;
|
||||
week_year_mode = 1;
|
||||
(*year)--;
|
||||
first_daynr -= (days = calc_days_in_year(*year));
|
||||
(yw.first)--;
|
||||
first_daynr -= (days = calc_days_in_year(yw.first));
|
||||
weekday = (weekday + 53 * 7 - days) % 7;
|
||||
}
|
||||
|
||||
@ -402,33 +404,29 @@ public:
|
||||
|
||||
if (week_year_mode && days >= 52 * 7)
|
||||
{
|
||||
weekday = (weekday + calc_days_in_year(*year)) % 7;
|
||||
weekday = (weekday + calc_days_in_year(yw.first)) % 7;
|
||||
if ((!first_weekday_mode && weekday < 4) || (first_weekday_mode && weekday == 0))
|
||||
{
|
||||
(*year)++;
|
||||
return 1;
|
||||
(yw.first)++;
|
||||
yw.second = 1;
|
||||
return yw;
|
||||
}
|
||||
}
|
||||
return days / 7 + 1;
|
||||
yw.second = days / 7 + 1;
|
||||
return yw;
|
||||
}
|
||||
|
||||
inline unsigned calc_yearWeek(DayNum d, UInt32 week_mode) const
|
||||
{
|
||||
UInt32 year = 0;
|
||||
UInt8 week = calc_week(d, week_mode | WEEK_YEAR, &year);
|
||||
return week + year * 100;
|
||||
}
|
||||
|
||||
/// Calculate week number of WEEK_NEWYEAR_DAY mode
|
||||
/// Calculate week number of WeekModeFlag::NEWYEAR_DAY mode
|
||||
/// The week number 1 is the first week in year that contains January 1,
|
||||
inline unsigned calc_newyear_week(DayNum d, bool monday_first_mode, UInt32 * year) const
|
||||
inline YearWeek toYearWeekOfNewyearMode(DayNum d, bool monday_first_mode) const
|
||||
{
|
||||
YearWeek yw(0, 0);
|
||||
UInt16 offset_day = monday_first_mode ? 0U : 1U;
|
||||
|
||||
// Checking the week across the year
|
||||
*year = toYear(DayNum(d + 7 - toDayOfWeek(DayNum(d + offset_day))));
|
||||
yw.first = toYear(DayNum(d + 7 - toDayOfWeek(DayNum(d + offset_day))));
|
||||
|
||||
DayNum first_day = makeDayNum(*year, 1, 1);
|
||||
DayNum first_day = makeDayNum(yw.first, 1, 1);
|
||||
DayNum this_day = d;
|
||||
|
||||
if (monday_first_mode)
|
||||
@ -445,60 +443,51 @@ public:
|
||||
if (toDayOfWeek(d) != 7)
|
||||
this_day = DayNum(d - toDayOfWeek(d));
|
||||
}
|
||||
return (this_day - first_day) / 7 + 1;
|
||||
yw.second = (this_day - first_day) / 7 + 1;
|
||||
return yw;
|
||||
}
|
||||
|
||||
inline unsigned check_week_mode(UInt32 mode) const
|
||||
/**
|
||||
* get first day of week with week_mode, return Sunday or Monday
|
||||
*/
|
||||
inline DayNum toFirstDayNumOfWeek(DayNum d, UInt8 week_mode) const
|
||||
{
|
||||
UInt32 week_format = (mode & 7);
|
||||
if (!(week_format & WEEK_MONDAY_FIRST))
|
||||
week_format ^= WEEK_FIRST_WEEKDAY;
|
||||
bool monday_first_mode = week_mode & static_cast<UInt8>(WeekModeFlag::MONDAY_FIRST);
|
||||
if (monday_first_mode)
|
||||
{
|
||||
return toFirstDayNumOfWeek(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (toDayOfWeek(d) != 7) ? DayNum(d - toDayOfWeek(d)) : d;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check and change mode to effective
|
||||
*/
|
||||
inline UInt8 check_week_mode(UInt8 mode) const
|
||||
{
|
||||
UInt8 week_format = (mode & 7);
|
||||
if (!(week_format & static_cast<UInt8>(WeekModeFlag::MONDAY_FIRST)))
|
||||
week_format ^= static_cast<UInt8>(WeekModeFlag::FIRST_WEEKDAY);
|
||||
return week_format;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate nr of day since year 0 in new date-system (from 1615)
|
||||
SYNOPSIS
|
||||
calc_daynr()
|
||||
year Year (exact 4 digit year, no year conversions)
|
||||
month Month
|
||||
day Day
|
||||
|
||||
NOTES: 0000-00-00 is a valid date, and will return 0
|
||||
|
||||
RETURN
|
||||
Days since 0000-00-00
|
||||
*/
|
||||
inline UInt64 calc_daynr(UInt32 year, UInt32 month, UInt32 day) const
|
||||
* Calc weekday from d
|
||||
* Returns 0 for monday, 1 for tuesday ...
|
||||
*/
|
||||
inline unsigned calc_weekday(DayNum d, bool sunday_first_day_of_week) const
|
||||
{
|
||||
UInt64 delsum;
|
||||
int temp;
|
||||
int y = year; /* may be < 0 temporarily */
|
||||
|
||||
if (y == 0 && month == 0)
|
||||
return 0; /* Skip errors */
|
||||
/* Cast to int to be able to handle month == 0 */
|
||||
delsum = static_cast<UInt64>(365 * y + 31 * (month - 1) + day);
|
||||
delsum = static_cast<UInt64>(365 * y + 31 * (static_cast<int>(month) - 1) + static_cast<int>(day));
|
||||
if (month <= 2)
|
||||
y--;
|
||||
if (!sunday_first_day_of_week)
|
||||
return toDayOfWeek(d) - 1;
|
||||
else
|
||||
delsum -= static_cast<UInt64>(static_cast<int>(month) * 4 + 23) / 10;
|
||||
temp = ((y / 100 + 1) * 3) / 4;
|
||||
return delsum + y / 4 - temp;
|
||||
} /* calc_daynr */
|
||||
|
||||
/*
|
||||
Calc weekday from daynr
|
||||
Returns 0 for monday, 1 for tuesday ...
|
||||
*/
|
||||
inline unsigned calc_weekday(UInt64 daynr, bool sunday_first_day_of_week) const
|
||||
{
|
||||
return (static_cast<UInt32>((daynr + 5L + (sunday_first_day_of_week ? 1L : 0L)) % 7));
|
||||
return toDayOfWeek(DayNum(d + 1)) - 1;
|
||||
}
|
||||
|
||||
/* Calc days in one year. */
|
||||
inline unsigned calc_days_in_year(UInt32 year) const
|
||||
inline unsigned calc_days_in_year(UInt16 year) const
|
||||
{
|
||||
return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366 : 365);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user