exprdatetime.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. //
  2. // Copyright (c) 2017-2026, Manticore Software LTD (https://manticoresearch.com)
  3. // Copyright (c) 2001-2016, Andrew Aksyonoff
  4. // Copyright (c) 2008-2016, Sphinx Technologies Inc
  5. // All rights reserved
  6. //
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License. You should have
  9. // received a copy of the GPL license along with this program; if you
  10. // did not, you can find it at http://www.gnu.org/
  11. //
  12. #include "exprdatetime.h"
  13. #include "exprtraits.h"
  14. static bool g_bUseUTC = false;
  15. static FORCE_INLINE int FormatTime ( time_t tTime, const BYTE ** ppStr )
  16. {
  17. cctz::civil_second tLocTime = ConvertTime(tTime);
  18. CSphString sVal;
  19. sVal.SetSprintf ( "%02d:%02d:%02d", tLocTime.hour(), tLocTime.minute(), tLocTime.second() );
  20. int iLength = sVal.Length();
  21. *ppStr = (const BYTE*) sVal.Leak();
  22. return iLength;
  23. }
  24. static FORCE_INLINE int FormatDate ( time_t tTime, const BYTE ** ppStr )
  25. {
  26. cctz::civil_second tLocTime = ConvertTime(tTime);
  27. CSphString sVal;
  28. sVal.SetSprintf ( "%04d-%02d-%02d", (int)tLocTime.year(), tLocTime.month(), tLocTime.day() );
  29. int iLength = sVal.Length();
  30. *ppStr = (const BYTE*) sVal.Leak();
  31. return iLength;
  32. }
  33. static FORCE_INLINE int FormatDayName ( time_t tTime, const BYTE ** ppStr )
  34. {
  35. static const char * dWeekDays[] =
  36. {
  37. "Sunday",
  38. "Monday",
  39. "Tuesday",
  40. "Wednesday",
  41. "Thursday",
  42. "Friday",
  43. "Saturday"
  44. };
  45. CSphString sVal = dWeekDays[GetWeekDay ( ConvertTime(tTime), true ) - 1];
  46. int iLength = sVal.Length();
  47. *ppStr = (const BYTE*) sVal.Leak();
  48. return iLength;
  49. }
  50. static FORCE_INLINE int FormatMonthName ( time_t tTime, const BYTE ** ppStr )
  51. {
  52. static const char * dMonths[] =
  53. {
  54. "January",
  55. "February",
  56. "March",
  57. "April",
  58. "May",
  59. "June",
  60. "July",
  61. "August",
  62. "September",
  63. "October",
  64. "November",
  65. "December"
  66. };
  67. CSphString sVal = dMonths[ConvertTime(tTime).month() - 1];
  68. int iLength = sVal.Length();
  69. *ppStr = (const BYTE*) sVal.Leak();
  70. return iLength;
  71. }
  72. /////////////////////////////////////////////////////////////////////
  73. template<bool UTC>
  74. class TimeTraits_T
  75. {
  76. protected:
  77. FORCE_INLINE cctz::civil_second GetConvertedTime ( ISphExpr * pExpr, const CSphMatch & tMatch ) const { return ConvertGroupbyTime<UTC> ( (time_t)pExpr->Int64Eval(tMatch) ); }
  78. };
  79. template<bool UTC>
  80. class Expr_TimeTraits_T : public Expr_Unary_c, public TimeTraits_T<UTC>
  81. {
  82. using Expr_Unary_c::Expr_Unary_c;
  83. public:
  84. float Eval ( const CSphMatch & tMatch ) const final { return (float)Int64Eval(tMatch); }
  85. int IntEval ( const CSphMatch & tMatch ) const final { return (int)Int64Eval(tMatch); }
  86. protected:
  87. FORCE_INLINE cctz::civil_second GetConvertedTime ( const CSphMatch & tMatch ) const { return TimeTraits_T<UTC>::GetConvertedTime ( m_pFirst, tMatch ); }
  88. };
  89. template<bool UTC>
  90. class Expr_TimeTraitsBinary_T : public Expr_Binary_c, public TimeTraits_T<UTC>
  91. {
  92. using Expr_Binary_c::Expr_Binary_c;
  93. public:
  94. float Eval ( const CSphMatch & tMatch ) const final { return (float)Int64Eval(tMatch); }
  95. int IntEval ( const CSphMatch & tMatch ) const final { return (int)Int64Eval(tMatch); }
  96. protected:
  97. FORCE_INLINE cctz::civil_second GetConvertedTime ( const CSphMatch & tMatch ) const { return TimeTraits_T<UTC>::GetConvertedTime ( m_pFirst, tMatch ); }
  98. };
  99. class Expr_Now_c : public Expr_NoLocator_c
  100. {
  101. public:
  102. Expr_Now_c ( int iNow ) : m_iNow ( iNow ) {}
  103. int IntEval ( const CSphMatch & ) const final { return m_iNow; }
  104. float Eval ( const CSphMatch & tMatch ) const final { return (float)IntEval ( tMatch ); }
  105. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return (int64_t)IntEval ( tMatch ); }
  106. uint64_t GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable ) final
  107. {
  108. EXPR_CLASS_NAME("Expr_Now_c");
  109. CALC_POD_HASH(m_iNow);
  110. return CALC_DEP_HASHES();
  111. }
  112. ISphExpr * Clone () const final { return new Expr_Now_c ( *this ); }
  113. private:
  114. int m_iNow {0};
  115. Expr_Now_c ( const Expr_Now_c & rhs) : m_iNow (rhs.m_iNow) {}
  116. };
  117. template<bool UTC, bool DATE>
  118. class Expr_CurTime_T : public ISphExpr
  119. {
  120. public:
  121. int IntEval ( const CSphMatch & ) const final
  122. {
  123. time_t tTime = time(nullptr);
  124. if constexpr ( UTC )
  125. return tTime;
  126. return PackLocalTimeAsUTC(tTime);
  127. }
  128. int StringEval ( const CSphMatch &, const BYTE ** ppStr ) const override
  129. {
  130. cctz::civil_second tLocTime;
  131. time_t tTime = time(nullptr);
  132. if constexpr ( UTC )
  133. tLocTime = ConvertTimeUTC(tTime);
  134. else
  135. tLocTime = ConvertTime(tTime);
  136. CSphString sVal;
  137. if constexpr ( DATE )
  138. sVal.SetSprintf ( "%04d-%02d-%02d %02d:%02d:%02d", (int)tLocTime.year(), tLocTime.month(), tLocTime.day(), tLocTime.hour(), tLocTime.minute(), tLocTime.second() );
  139. else
  140. sVal.SetSprintf ( "%02d:%02d:%02d", tLocTime.hour(), tLocTime.minute(), tLocTime.second() );
  141. int iLength = sVal.Length();
  142. *ppStr = (const BYTE*) sVal.Leak();
  143. return iLength;
  144. }
  145. float Eval ( const CSphMatch & tMatch ) const final { return (float)IntEval ( tMatch ); }
  146. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return (int64_t)IntEval ( tMatch ); }
  147. bool IsDataPtrAttr () const final { return true; }
  148. void FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema ) final {}
  149. ISphExpr * Clone() const override { return new Expr_CurTime_T; }
  150. uint64_t GetHash ( const ISphSchema &, uint64_t, bool & bDisable ) final
  151. {
  152. bDisable = true;
  153. return 0;
  154. }
  155. };
  156. class Expr_CurDate_c : public Expr_CurTime_T<false,false>
  157. {
  158. public:
  159. int StringEval ( const CSphMatch &, const BYTE ** ppStr ) const final { return FormatDate ( time(nullptr), ppStr ); }
  160. ISphExpr * Clone() const final { return new Expr_CurDate_c; }
  161. };
  162. class Expr_Time_c : public Expr_TimeTraits_T<false>
  163. {
  164. using BASE = Expr_TimeTraits_T<false>;
  165. using BASE::BASE;
  166. public:
  167. Expr_Time_c ( ISphExpr * pExpr ) : BASE ( "Expr_Time_c", pExpr ) {}
  168. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return m_pFirst->IntEval(tMatch); }
  169. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const override { return FormatTime ( m_pFirst->IntEval(tMatch), ppStr ); }
  170. bool IsDataPtrAttr () const final { return true; }
  171. ISphExpr * Clone() const override { return new Expr_Time_c(*this); }
  172. };
  173. class Expr_Date_c : public Expr_TimeTraits_T<false>
  174. {
  175. using BASE = Expr_TimeTraits_T<false>;
  176. using BASE::BASE;
  177. public:
  178. Expr_Date_c ( ISphExpr * pExpr ) : BASE ( "Expr_Date_c", pExpr ) {}
  179. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return m_pFirst->IntEval(tMatch); }
  180. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const override { return FormatDate ( m_pFirst->IntEval(tMatch), ppStr ); }
  181. bool IsDataPtrAttr () const final { return true; }
  182. ISphExpr * Clone() const override { return new Expr_Date_c(*this); }
  183. };
  184. class Expr_StringUnary_c : public Expr_Unary_c
  185. {
  186. using Expr_Unary_c::Expr_Unary_c;
  187. public:
  188. float Eval ( const CSphMatch & ) const final { assert ( 0 && "one just does not simply evaluate a string as float" ); return 0; }
  189. int IntEval ( const CSphMatch & ) const final { assert ( 0 && "one just does not simply evaluate a string as int" ); return 0; }
  190. int64_t Int64Eval ( const CSphMatch & ) const final { assert ( 0 && "one just does not simply evaluate a string as bigint" ); return 0; }
  191. bool IsDataPtrAttr () const final { return true; }
  192. };
  193. class Expr_DayName_c : public Expr_StringUnary_c
  194. {
  195. using Expr_StringUnary_c::Expr_StringUnary_c;
  196. public:
  197. Expr_DayName_c ( ISphExpr * pExpr ) : Expr_StringUnary_c ( "Expr_DayName_c", pExpr ) {}
  198. ISphExpr * Clone() const override { return new Expr_DayName_c(*this); }
  199. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const override { return FormatDayName ( m_pFirst->IntEval(tMatch), ppStr ); }
  200. };
  201. class Expr_MonthName_c : public Expr_StringUnary_c
  202. {
  203. using Expr_StringUnary_c::Expr_StringUnary_c;
  204. public:
  205. Expr_MonthName_c ( ISphExpr * pExpr ) : Expr_StringUnary_c ( "Expr_MonthName_c", pExpr ) {}
  206. ISphExpr * Clone() const override { return new Expr_MonthName_c(*this); }
  207. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const override { return FormatMonthName ( m_pFirst->IntEval(tMatch), ppStr ); }
  208. };
  209. class Expr_TimeDiff_c : public Expr_Binary_c
  210. {
  211. public:
  212. Expr_TimeDiff_c ( ISphExpr * pFirst, ISphExpr * pSecond )
  213. : Expr_Binary_c ( "Expr_TimeDiff_c", pFirst, pSecond )
  214. {}
  215. int IntEval ( const CSphMatch & tMatch ) const final
  216. {
  217. assert ( m_pFirst && m_pSecond );
  218. return m_pFirst->IntEval ( tMatch )-m_pSecond->IntEval ( tMatch );
  219. }
  220. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const final
  221. {
  222. int iVal = IntEval ( tMatch );
  223. CSphString sVal;
  224. int t = iVal<0 ? -iVal : iVal;
  225. sVal.SetSprintf ( "%s%02d:%02d:%02d", iVal<0 ? "-" : "", t/60/60, (t/60)%60, t%60 );
  226. int iLength = sVal.Length();
  227. *ppStr = (const BYTE*) sVal.Leak();
  228. return iLength;
  229. }
  230. float Eval ( const CSphMatch & tMatch ) const final { return (float)IntEval ( tMatch ); }
  231. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return (int64_t)IntEval ( tMatch ); }
  232. bool IsDataPtrAttr() const final { return true; }
  233. ISphExpr * Clone() const final { return new Expr_TimeDiff_c ( *this ); }
  234. };
  235. class Expr_DateDiff_c : public Expr_Binary_c
  236. {
  237. public:
  238. Expr_DateDiff_c ( ISphExpr * pFirst, ISphExpr * pSecond )
  239. : Expr_Binary_c ( "Expr_DateDiff_c", pFirst, pSecond )
  240. {}
  241. int IntEval ( const CSphMatch & tMatch ) const final
  242. {
  243. assert ( m_pFirst && m_pSecond );
  244. cctz::civil_day tDay1 = cctz::civil_day ( ConvertTime ( m_pFirst->IntEval(tMatch) ) );
  245. cctz::civil_day tDay2 = cctz::civil_day ( ConvertTime ( m_pSecond->IntEval(tMatch) ) );
  246. return tDay1-tDay2;
  247. }
  248. float Eval ( const CSphMatch & tMatch ) const final { return (float)IntEval ( tMatch ); }
  249. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return (int64_t)IntEval ( tMatch ); }
  250. ISphExpr * Clone() const final { return new Expr_DateDiff_c ( *this ); }
  251. };
  252. class ExprDateFormat_c : public ISphStringExpr
  253. {
  254. public:
  255. ExprDateFormat_c ( ISphExpr * pArg, ISphExpr * pFmt )
  256. : m_pArg ( pArg )
  257. {
  258. assert( pArg );
  259. SafeAddRef( pArg );
  260. CSphMatch tTmp;
  261. const BYTE * sVal = nullptr;
  262. int iLen = pFmt->StringEval ( tTmp, &sVal );
  263. m_sFmt = CSphString ( (const char*)sVal, iLen );
  264. FreeDataPtr ( pFmt, sVal );
  265. }
  266. int StringEval ( const CSphMatch & tMatch, const BYTE ** ppStr ) const final
  267. {
  268. int64_t iTime = m_pArg->Int64Eval ( tMatch );
  269. // FIXME: modify this to use static buffer (performance issue)
  270. CSphString sRes = FormatTime ( time_t(iTime), m_sFmt.cstr() );
  271. int iLen = sRes.Length();
  272. *ppStr = (const BYTE *)sRes.Leak();
  273. return iLen;
  274. }
  275. void FixupLocator ( const ISphSchema * pOldSchema, const ISphSchema * pNewSchema ) override
  276. {
  277. if ( m_pArg )
  278. m_pArg->FixupLocator ( pOldSchema, pNewSchema );
  279. }
  280. void Command ( ESphExprCommand eCmd, void * pArg ) override
  281. {
  282. if ( m_pArg )
  283. m_pArg->Command ( eCmd, pArg );
  284. }
  285. bool IsDataPtrAttr() const final
  286. {
  287. return true;
  288. }
  289. bool IsConst () const final { return false; }
  290. ISphExpr * Clone () const final
  291. {
  292. return new ExprDateFormat_c ( *this );
  293. }
  294. uint64_t GetHash ( const ISphSchema & tSorterSchema, uint64_t uPrevHash, bool & bDisable ) final
  295. {
  296. EXPR_CLASS_NAME("ExprDateFormat_c");
  297. CALC_CHILD_HASH(m_pArg);
  298. return CALC_DEP_HASHES();
  299. }
  300. private:
  301. ExprDateFormat_c ( const ExprDateFormat_c & rhs )
  302. : m_pArg ( SafeClone ( rhs.m_pArg ) )
  303. , m_sFmt ( rhs.m_sFmt )
  304. {}
  305. CSphRefcountedPtr<ISphExpr> m_pArg;
  306. CSphString m_sFmt;
  307. };
  308. template<bool UTC>
  309. class Expr_Day_T : public Expr_TimeTraits_T<UTC>
  310. {
  311. using BASE=Expr_TimeTraits_T<UTC>;
  312. public:
  313. Expr_Day_T ( ISphExpr * pExpr ) : BASE ( "Expr_Day_T", pExpr ) {}
  314. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).day(); }
  315. ISphExpr * Clone() const final { return new Expr_Day_T(*this); }
  316. };
  317. template<bool UTC>
  318. class Expr_Week_T : public Expr_TimeTraitsBinary_T<UTC>
  319. {
  320. using BASE=Expr_TimeTraitsBinary_T<UTC>;
  321. public:
  322. Expr_Week_T ( ISphExpr * pFirst, ISphExpr * pSecond ) : BASE ( "Expr_Week_T", pFirst, pSecond )
  323. {
  324. if ( !pSecond || pSecond->IsConst() )
  325. {
  326. m_bConst = true;
  327. if ( pSecond )
  328. {
  329. CSphMatch tMatch;
  330. m_uFlags = pSecond->IntEval(tMatch);
  331. }
  332. }
  333. }
  334. int64_t Int64Eval ( const CSphMatch & tMatch ) const final
  335. {
  336. if ( m_bConst )
  337. return CalcWeekNumber ( BASE::GetConvertedTime(tMatch), m_uFlags );
  338. return CalcWeekNumber ( BASE::GetConvertedTime(tMatch), BASE::m_pSecond->IntEval(tMatch) );
  339. }
  340. ISphExpr * Clone() const final { return new Expr_Week_T(*this); }
  341. private:
  342. bool m_bConst = false;
  343. uint32_t m_uFlags = 3;
  344. };
  345. template<bool UTC>
  346. class Expr_Month_T : public Expr_TimeTraits_T<UTC>
  347. {
  348. using BASE=Expr_TimeTraits_T<UTC>;
  349. public:
  350. Expr_Month_T ( ISphExpr * pExpr ) : BASE ( "Expr_Month_T", pExpr ) {}
  351. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).month(); }
  352. ISphExpr * Clone() const final { return new Expr_Month_T(*this); }
  353. };
  354. template<bool UTC>
  355. class Expr_Year_T : public Expr_TimeTraits_T<UTC>
  356. {
  357. using BASE=Expr_TimeTraits_T<UTC>;
  358. public:
  359. Expr_Year_T ( ISphExpr * pExpr ) : BASE ( "Expr_Year_T", pExpr ) {}
  360. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).year(); }
  361. ISphExpr * Clone() const final { return new Expr_Year_T(*this); }
  362. };
  363. template<bool UTC>
  364. class Expr_YearMonth_T : public Expr_TimeTraits_T<UTC>
  365. {
  366. using BASE=Expr_TimeTraits_T<UTC>;
  367. public:
  368. Expr_YearMonth_T ( ISphExpr * pExpr ) : BASE ( "Expr_YearMonth_T", pExpr ) {}
  369. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return CalcYearMonth ( BASE::GetConvertedTime(tMatch) ); }
  370. ISphExpr * Clone() const final { return new Expr_YearMonth_T(*this); }
  371. };
  372. template<bool UTC>
  373. class Expr_YearMonthDay_T : public Expr_TimeTraits_T<UTC>
  374. {
  375. using BASE=Expr_TimeTraits_T<UTC>;
  376. public:
  377. Expr_YearMonthDay_T ( ISphExpr * pExpr ) : BASE ( "Expr_YearMonthDay_T", pExpr ) {}
  378. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return CalcYearMonthDay ( BASE::GetConvertedTime(tMatch) ); }
  379. ISphExpr * Clone() const final { return new Expr_YearMonthDay_T(*this); }
  380. };
  381. template<bool UTC>
  382. class Expr_YearWeek_T : public Expr_TimeTraits_T<UTC>
  383. {
  384. using BASE=Expr_TimeTraits_T<UTC>;
  385. public:
  386. Expr_YearWeek_T ( ISphExpr * pExpr ) : BASE ( "Expr_YearWeek_T", pExpr ) {}
  387. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return CalcYearWeek ( BASE::GetConvertedTime(tMatch) ); }
  388. ISphExpr * Clone() const final { return new Expr_YearWeek_T(*this); }
  389. };
  390. template<bool UTC>
  391. class Expr_Hour_T : public Expr_TimeTraits_T<UTC>
  392. {
  393. using BASE=Expr_TimeTraits_T<UTC>;
  394. public:
  395. Expr_Hour_T ( ISphExpr * pExpr ) : BASE ( "Expr_Hour_T", pExpr ) {}
  396. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).hour(); }
  397. ISphExpr * Clone() const final { return new Expr_Hour_T(*this); }
  398. };
  399. template<bool UTC>
  400. class Expr_Minute_T : public Expr_TimeTraits_T<UTC>
  401. {
  402. using BASE=Expr_TimeTraits_T<UTC>;
  403. public:
  404. Expr_Minute_T ( ISphExpr * pExpr ) : BASE ( "Expr_Minute_T", pExpr ) {}
  405. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).minute(); }
  406. ISphExpr * Clone() const final { return new Expr_Minute_T(*this); }
  407. };
  408. template<bool UTC>
  409. class Expr_Second_T : public Expr_TimeTraits_T<UTC>
  410. {
  411. using BASE=Expr_TimeTraits_T<UTC>;
  412. public:
  413. Expr_Second_T ( ISphExpr * pExpr ) : BASE ( "Expr_Second_T", pExpr ) {}
  414. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return BASE::GetConvertedTime(tMatch).second(); }
  415. ISphExpr * Clone() const final { return new Expr_Second_T(*this); }
  416. };
  417. template<bool UTC>
  418. class Expr_DayOfWeek_T : public Expr_TimeTraits_T<UTC>
  419. {
  420. using BASE=Expr_TimeTraits_T<UTC>;
  421. public:
  422. Expr_DayOfWeek_T ( ISphExpr * pExpr ) : BASE ( "Expr_DayOfWeek_T", pExpr ) {}
  423. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return GetWeekDay ( BASE::GetConvertedTime(tMatch), true ); }
  424. ISphExpr * Clone() const final { return new Expr_DayOfWeek_T(*this); }
  425. };
  426. template<bool UTC>
  427. class Expr_DayOfYear_T : public Expr_TimeTraits_T<UTC>
  428. {
  429. using BASE=Expr_TimeTraits_T<UTC>;
  430. public:
  431. Expr_DayOfYear_T ( ISphExpr * pExpr ) : BASE ( "Expr_DayOfYear_T", pExpr ) {}
  432. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return GetYearDay ( BASE::GetConvertedTime(tMatch) ); }
  433. ISphExpr * Clone() const final { return new Expr_DayOfYear_T(*this); }
  434. };
  435. template<bool UTC>
  436. class Expr_Quarter_T : public Expr_TimeTraits_T<UTC>
  437. {
  438. using BASE=Expr_TimeTraits_T<UTC>;
  439. public:
  440. Expr_Quarter_T ( ISphExpr * pExpr ) : BASE ( "Expr_Quarter_T", pExpr ) {}
  441. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return GetQuarter ( BASE::GetConvertedTime(tMatch) ); }
  442. ISphExpr * Clone() const final { return new Expr_Quarter_T(*this); }
  443. };
  444. class Expr_DateAdd_c : public Expr_Binary_c
  445. {
  446. public:
  447. Expr_DateAdd_c ( ISphExpr * pFirst, ISphExpr * pSecond, TimeUnit_e eUnit, bool bAdd );
  448. int IntEval ( const CSphMatch & tMatch ) const final;
  449. float Eval ( const CSphMatch & tMatch ) const final { return (float)IntEval ( tMatch ); }
  450. int64_t Int64Eval ( const CSphMatch & tMatch ) const final { return (int64_t)IntEval ( tMatch ); }
  451. ISphExpr * Clone() const final { return new Expr_DateAdd_c ( *this ); }
  452. private:
  453. TimeUnit_e m_eUnit = TimeUnit_e::SECOND;
  454. bool m_bAdd = true;
  455. bool m_bConst = true;
  456. int m_iAdd = 0;
  457. };
  458. Expr_DateAdd_c::Expr_DateAdd_c ( ISphExpr * pFirst, ISphExpr * pSecond, TimeUnit_e eUnit, bool bAdd )
  459. : Expr_Binary_c ( "Expr_DateAdd_c", pFirst, pSecond )
  460. , m_eUnit ( eUnit )
  461. , m_bAdd ( bAdd )
  462. {
  463. m_bConst = m_pSecond->IsConst();
  464. if ( m_bConst )
  465. {
  466. CSphMatch tMatch;
  467. m_iAdd = m_pSecond->IntEval(tMatch);
  468. }
  469. }
  470. int Expr_DateAdd_c::IntEval ( const CSphMatch & tMatch ) const
  471. {
  472. cctz::civil_second tCS = ConvertTime ( m_pFirst->IntEval(tMatch) );
  473. int iAdd = m_bConst ? m_iAdd : m_pSecond->IntEval(tMatch);
  474. iAdd *= m_bAdd ? 1 : -1;
  475. switch ( m_eUnit )
  476. {
  477. case TimeUnit_e::SECOND:
  478. return ConvertTime ( cctz::civil_second ( tCS.year(), tCS.month(), tCS.day(), tCS.hour(), tCS.minute(), tCS.second() + iAdd ) );
  479. case TimeUnit_e::MINUTE:
  480. return ConvertTime ( cctz::civil_second ( tCS.year(), tCS.month(), tCS.day(), tCS.hour(), tCS.minute() + iAdd, tCS.second() ) );
  481. case TimeUnit_e::HOUR:
  482. return ConvertTime ( cctz::civil_second ( tCS.year(), tCS.month(), tCS.day(), tCS.hour() + iAdd, tCS.minute(), tCS.second() ) );
  483. case TimeUnit_e::DAY:
  484. case TimeUnit_e::WEEK:
  485. {
  486. iAdd *= m_eUnit==TimeUnit_e::WEEK ? 7 : 1;
  487. return ConvertTime ( cctz::civil_second ( tCS.year(), tCS.month(), tCS.day() + iAdd, tCS.hour(), tCS.minute(), tCS.second() ) );
  488. }
  489. case TimeUnit_e::MONTH:
  490. case TimeUnit_e::QUARTER:
  491. {
  492. iAdd *= m_eUnit==TimeUnit_e::QUARTER ? 3 : 1;
  493. const auto tNextMonth = cctz::civil_month(tCS) + iAdd;
  494. const auto tLastDayOfNextMonth = cctz::civil_second ( cctz::civil_day(tNextMonth + 1) - 1 );
  495. const auto tNormalized = cctz::civil_second ( tCS.year(), tCS.month() + iAdd, tCS.day(), tCS.hour(), tCS.minute(), tCS.second() );
  496. return ConvertTime ( std::min ( tNormalized, tLastDayOfNextMonth ) );
  497. }
  498. case TimeUnit_e::YEAR:
  499. return ConvertTime ( cctz::civil_second ( tCS.year() + iAdd, tCS.month(), tCS.day(), tCS.hour(), tCS.minute(), tCS.second() ) );
  500. default:
  501. assert ( 0 && "Unknown time unit" );
  502. return 0;
  503. }
  504. }
  505. void SetGroupingInUTC ( bool bGroupingInUtc )
  506. {
  507. g_bUseUTC = bGroupingInUtc;
  508. }
  509. bool GetGroupingInUTC()
  510. {
  511. return g_bUseUTC;
  512. }
  513. ISphExpr * CreateExprNow ( int iNow )
  514. {
  515. return new Expr_Now_c(iNow);
  516. }
  517. ISphExpr * CreateExprDateFormat ( ISphExpr * pArg, ISphExpr * pFmt )
  518. {
  519. return new ExprDateFormat_c ( pArg, pFmt );
  520. }
  521. ISphExpr * CreateExprCurTime ( bool bUTC, bool bDate )
  522. {
  523. int iIndex = 2*(bUTC ? 1 : 0) + (bDate ? 1 : 0);
  524. switch ( iIndex )
  525. {
  526. case 0: return new Expr_CurTime_T<false,false>;
  527. case 1: return new Expr_CurTime_T<false,true>;
  528. case 2: return new Expr_CurTime_T<true,false>;
  529. case 3: return new Expr_CurTime_T<true,true>;
  530. default:
  531. assert ( 0 && "CreateExprTime error" );
  532. return nullptr;
  533. }
  534. }
  535. ISphExpr * CreateExprCurDate()
  536. {
  537. return new Expr_CurDate_c;
  538. }
  539. ISphExpr * CreateExprTime ( ISphExpr * pArg )
  540. {
  541. return new Expr_Time_c(pArg);
  542. }
  543. ISphExpr * CreateExprDate ( ISphExpr * pArg )
  544. {
  545. return new Expr_Date_c(pArg);
  546. }
  547. ISphExpr * CreateExprDayName ( ISphExpr * pArg )
  548. {
  549. return new Expr_DayName_c(pArg);
  550. }
  551. ISphExpr * CreateExprMonthName ( ISphExpr * pArg )
  552. {
  553. return new Expr_MonthName_c(pArg);
  554. }
  555. ISphExpr * CreateExprTimeDiff ( ISphExpr * pFirst, ISphExpr * pSecond )
  556. {
  557. return new Expr_TimeDiff_c ( pFirst, pSecond );
  558. }
  559. ISphExpr * CreateExprDateDiff ( ISphExpr * pFirst, ISphExpr * pSecond )
  560. {
  561. return new Expr_DateDiff_c ( pFirst, pSecond );
  562. }
  563. ISphExpr * CreateExprDateAdd ( ISphExpr * pFirst, ISphExpr * pSecond, TimeUnit_e eUnit, bool bAdd )
  564. {
  565. return new Expr_DateAdd_c ( pFirst, pSecond, eUnit, bAdd );
  566. }
  567. ISphExpr * CreateExprDay ( ISphExpr * pExpr )
  568. {
  569. return g_bUseUTC ? (ISphExpr *)new Expr_Day_T<true>(pExpr) : (ISphExpr *)new Expr_Day_T<false>(pExpr);
  570. }
  571. ISphExpr * CreateExprWeek ( ISphExpr * pFirst, ISphExpr * pSecond )
  572. {
  573. return g_bUseUTC ? (ISphExpr *)new Expr_Week_T<true>( pFirst, pSecond ) : (ISphExpr *)new Expr_Week_T<false>( pFirst, pSecond );
  574. }
  575. ISphExpr * CreateExprMonth ( ISphExpr * pExpr )
  576. {
  577. return g_bUseUTC ? (ISphExpr *)new Expr_Month_T<true>(pExpr) : (ISphExpr *)new Expr_Month_T<false>(pExpr);
  578. }
  579. ISphExpr * CreateExprYear ( ISphExpr * pExpr )
  580. {
  581. return g_bUseUTC ? (ISphExpr *)new Expr_Year_T<true>(pExpr) : (ISphExpr *)new Expr_Year_T<false>(pExpr);
  582. }
  583. ISphExpr * CreateExprYearMonth ( ISphExpr * pExpr )
  584. {
  585. return g_bUseUTC ? (ISphExpr *)new Expr_YearMonth_T<true>(pExpr) : (ISphExpr *)new Expr_YearMonth_T<false>(pExpr);
  586. }
  587. ISphExpr * CreateExprYearMonthDay ( ISphExpr * pExpr )
  588. {
  589. return g_bUseUTC ? (ISphExpr *)new Expr_YearMonthDay_T<true>(pExpr) : (ISphExpr *)new Expr_YearMonthDay_T<false>(pExpr);
  590. }
  591. ISphExpr * CreateExprYearWeek ( ISphExpr * pExpr )
  592. {
  593. return g_bUseUTC ? (ISphExpr *)new Expr_YearWeek_T<true>(pExpr) : (ISphExpr *)new Expr_YearWeek_T<false>(pExpr);
  594. }
  595. ISphExpr * CreateExprHour ( ISphExpr * pExpr )
  596. {
  597. return g_bUseUTC ? (ISphExpr *)new Expr_Hour_T<true>(pExpr) : (ISphExpr *)new Expr_Hour_T<false>(pExpr);
  598. }
  599. ISphExpr * CreateExprMinute ( ISphExpr * pExpr )
  600. {
  601. return g_bUseUTC ? (ISphExpr *)new Expr_Minute_T<true>(pExpr) : (ISphExpr *)new Expr_Minute_T<false>(pExpr);
  602. }
  603. ISphExpr * CreateExprSecond ( ISphExpr * pExpr )
  604. {
  605. return g_bUseUTC ? (ISphExpr *)new Expr_Second_T<true>(pExpr) : (ISphExpr *)new Expr_Second_T<false>(pExpr);
  606. }
  607. ISphExpr * CreateExprDayOfWeek ( ISphExpr * pExpr )
  608. {
  609. return g_bUseUTC ? (ISphExpr *)new Expr_DayOfWeek_T<true>(pExpr) : (ISphExpr *)new Expr_DayOfWeek_T<false>(pExpr);
  610. }
  611. ISphExpr * CreateExprDayOfYear ( ISphExpr * pExpr )
  612. {
  613. return g_bUseUTC ? (ISphExpr *)new Expr_DayOfYear_T<true>(pExpr) : (ISphExpr *)new Expr_DayOfYear_T<false>(pExpr);
  614. }
  615. ISphExpr * CreateExprQuarter ( ISphExpr * pExpr )
  616. {
  617. return g_bUseUTC ? (ISphExpr *)new Expr_Quarter_T<true>(pExpr) : (ISphExpr *)new Expr_Quarter_T<false>(pExpr);
  618. }