Date Time.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. static CChar8 *_MonthNameShort[12]=
  6. {
  7. "Jan",
  8. "Feb",
  9. "Mar",
  10. "Apr",
  11. "May",
  12. "Jun",
  13. "Jul",
  14. "Aug",
  15. "Sep",
  16. "Oct",
  17. "Nov",
  18. "Dec",
  19. };
  20. static CChar8 *_MonthName[12]=
  21. {
  22. "January",
  23. "February",
  24. "March",
  25. "April",
  26. "May",
  27. "June",
  28. "July",
  29. "August",
  30. "September",
  31. "October",
  32. "November",
  33. "December",
  34. };
  35. static const Byte _MonthDays[12]=
  36. {
  37. 31, // Jan
  38. 28, // Feb
  39. 31, // Mar
  40. 30, // Apr
  41. 31, // May
  42. 30, // Jun
  43. 31, // Jul
  44. 31, // Aug
  45. 30, // Sep
  46. 31, // Oct
  47. 30, // Nov
  48. 31, // Dec
  49. };
  50. static const Int MonthDaysAccumulated[12]=
  51. {
  52. 0,
  53. _MonthDays[ 0]+MonthDaysAccumulated[ 0],
  54. _MonthDays[ 1]+MonthDaysAccumulated[ 1],
  55. _MonthDays[ 2]+MonthDaysAccumulated[ 2],
  56. _MonthDays[ 3]+MonthDaysAccumulated[ 3],
  57. _MonthDays[ 4]+MonthDaysAccumulated[ 4],
  58. _MonthDays[ 5]+MonthDaysAccumulated[ 5],
  59. _MonthDays[ 6]+MonthDaysAccumulated[ 6],
  60. _MonthDays[ 7]+MonthDaysAccumulated[ 7],
  61. _MonthDays[ 8]+MonthDaysAccumulated[ 8],
  62. _MonthDays[ 9]+MonthDaysAccumulated[ 9],
  63. _MonthDays[10]+MonthDaysAccumulated[10],
  64. };
  65. /******************************************************************************/
  66. // DATE TIME
  67. /******************************************************************************/
  68. Bool DateTime::valid()C
  69. {
  70. if(InRange(second, 60) // second>=0 && second<=59
  71. && InRange(minute, 60) // minute>=0 && minute<=59
  72. && InRange(hour , 24) // hour >=0 && hour <=23
  73. && day >=1 && day <=31
  74. && month >=1 && month <=12)
  75. {
  76. if(day<=_MonthDays[month-1] )return true;
  77. if(month==2 && day==29 && LeapYear(year))return true;
  78. }
  79. return false;
  80. }
  81. Int DateTime::days()C
  82. {
  83. Int leap_years=(year+3)/4 - 3*((year-1)/400) - ((year-1)%400)/100 + (LeapYear(year) && month>=3);
  84. return year*365 + MonthDaysAccumulated[Mid(month, 1, 12)-1] + day-1 + leap_years; // each leap year has 1 extra day
  85. }
  86. Long DateTime::seconds()C
  87. {
  88. return Long(days())*(60*60*24) + (hour*(60*60) + minute*60 + second);
  89. }
  90. Str DateTime::asText(Bool include_seconds)C
  91. {
  92. Char8 temp[256];
  93. Str s; s.reserve(4+1+2+1+2+1+2+1+2+(include_seconds ? 1+2 : 0));
  94. s+=TextInt(year, temp); s+='-'; s+=TextInt(month, temp, 2); s+='-'; s+=TextInt(day, temp, 2);
  95. s+=' '; s+=TextInt(hour, temp, 2); s+=':'; s+=TextInt(minute, temp, 2); if(include_seconds){s+=':'; s+=TextInt(second, temp, 2);}
  96. return s;
  97. }
  98. Str DateTime::asFileName(Bool include_seconds)C
  99. {
  100. Char8 temp[256];
  101. Str s; s.reserve(4+1+2+1+2+1+2+1+2+(include_seconds ? 1+2 : 0));
  102. s=TextInt(year, temp); s+='-'; s+=TextInt(month, temp, 2); s+='-'; s+=TextInt(day, temp, 2);
  103. s+=' '; s+=TextInt(hour, temp, 2); s+=','; s+=TextInt(minute, temp, 2); if(include_seconds){s+=','; s+=TextInt(second, temp, 2);}
  104. return s;
  105. }
  106. /******************************************************************************/
  107. DateTime & DateTime ::zero() {Zero(T); return T;}
  108. DateTimeMs& DateTimeMs::zero() {Zero(T); return T;}
  109. DateTime& DateTime::getLocal()
  110. {
  111. #if WINDOWS
  112. SYSTEMTIME time; GetLocalTime(&time);
  113. second=time.wSecond;
  114. minute=time.wMinute;
  115. hour =time.wHour;
  116. day =time.wDay;
  117. month =time.wMonth;
  118. year =time.wYear;
  119. #else
  120. tm t; time_t sec=time(null); localtime_r(&sec, &t);
  121. year =t.tm_year+1900;
  122. month =t.tm_mon+1;
  123. day =t.tm_mday;
  124. hour =t.tm_hour;
  125. minute=t.tm_min;
  126. second=t.tm_sec;
  127. #endif
  128. return T;
  129. }
  130. DateTimeMs& DateTimeMs::getLocal()
  131. {
  132. #if WINDOWS
  133. SYSTEMTIME time; GetLocalTime(&time);
  134. millisecond=time.wMilliseconds;
  135. second =time.wSecond;
  136. minute =time.wMinute;
  137. hour =time.wHour;
  138. day =time.wDay;
  139. month =time.wMonth;
  140. year =time.wYear;
  141. #else
  142. tm t; timeval tv; gettimeofday(&tv, null); localtime_r(&tv.tv_sec, &t);
  143. year =t.tm_year+1900;
  144. month =t.tm_mon+1;
  145. day =t.tm_mday;
  146. hour =t.tm_hour;
  147. minute =t.tm_min;
  148. second =t.tm_sec;
  149. millisecond=tv.tv_usec/1000;
  150. #endif
  151. return T;
  152. }
  153. DateTime& DateTime::getUTC()
  154. {
  155. #if WINDOWS
  156. SYSTEMTIME time; GetSystemTime(&time);
  157. second=time.wSecond;
  158. minute=time.wMinute;
  159. hour =time.wHour;
  160. day =time.wDay;
  161. month =time.wMonth;
  162. year =time.wYear;
  163. #else
  164. tm t; time_t sec=time(null); gmtime_r(&sec, &t);
  165. year =t.tm_year+1900;
  166. month =t.tm_mon+1;
  167. day =t.tm_mday;
  168. hour =t.tm_hour;
  169. minute=t.tm_min;
  170. second=t.tm_sec;
  171. #endif
  172. return T;
  173. }
  174. DateTimeMs& DateTimeMs::getUTC()
  175. {
  176. #if WINDOWS
  177. SYSTEMTIME time; GetSystemTime(&time);
  178. millisecond=time.wMilliseconds;
  179. second =time.wSecond;
  180. minute =time.wMinute;
  181. hour =time.wHour;
  182. day =time.wDay;
  183. month =time.wMonth;
  184. year =time.wYear;
  185. #else
  186. timeval tv; gettimeofday(&tv, null);
  187. super::from1970s(tv.tv_sec);
  188. millisecond=tv.tv_usec/1000;
  189. #endif
  190. return T;
  191. }
  192. DateTime& DateTime::incMonth()
  193. {
  194. if(++month>12){month=1; year++;}
  195. return T;
  196. }
  197. DateTime& DateTime::decMonth()
  198. {
  199. if(--month<1){month=12; year--;}
  200. return T;
  201. }
  202. DateTime& DateTime::incDay()
  203. {
  204. if(++day>28)
  205. {
  206. if(day>MonthDays(month, year))
  207. {
  208. day=1;
  209. incMonth();
  210. }
  211. }
  212. return T;
  213. }
  214. DateTime& DateTime::decDay()
  215. {
  216. if(day>1)day--;else
  217. {
  218. decMonth();
  219. day=MonthDays(month, year); // set 'day' after having new 'month'
  220. }
  221. return T;
  222. }
  223. DateTime& DateTime::incHour()
  224. {
  225. if(++hour>=24){hour=0; incDay();}
  226. return T;
  227. }
  228. DateTime& DateTime::decHour()
  229. {
  230. if(hour>0)hour--;else{hour=23; decDay();}
  231. return T;
  232. }
  233. DateTime& DateTime::incMinute()
  234. {
  235. if(++minute>=60){minute=0; incHour();}
  236. return T;
  237. }
  238. DateTime& DateTime::decMinute()
  239. {
  240. if(minute>0)minute--;else{minute=59; decHour();}
  241. return T;
  242. }
  243. DateTime& DateTime::incSecond()
  244. {
  245. if(++second>=60){second=0; incMinute();}
  246. return T;
  247. }
  248. DateTime& DateTime::decSecond()
  249. {
  250. if(second>0)second--;else{second=59; decMinute();}
  251. return T;
  252. }
  253. #if ANDROID && __ANDROID_API__<12 // Android below API 12 doesn't have 'timegm'
  254. static SyncLock mktime_lock;
  255. time_t timegm(struct tm *tm)
  256. {
  257. SyncLocker locker(mktime_lock);
  258. char *tz=getenv("TZ"); setenv("TZ", "", 1);
  259. tzset();
  260. time_t ret=mktime(tm);
  261. if(tz)setenv("TZ", tz, 1);else unsetenv("TZ");
  262. tzset();
  263. return ret;
  264. }
  265. #endif
  266. DateTime& DateTime::toUTC()
  267. {
  268. if(valid())
  269. {
  270. #if WINDOWS
  271. SYSTEMTIME local, utc;
  272. local.wYear =year;
  273. local.wMonth =month;
  274. local.wDay =day;
  275. local.wHour =hour;
  276. local.wMinute=minute;
  277. local.wSecond=second;
  278. local.wDayOfWeek =0;
  279. local.wMilliseconds=0;
  280. if(TzSpecificLocalTimeToSystemTime(null, &local, &utc))
  281. {
  282. year =utc.wYear;
  283. month =utc.wMonth;
  284. day =utc.wDay;
  285. hour =utc.wHour;
  286. minute=utc.wMinute;
  287. second=utc.wSecond;
  288. }
  289. #else
  290. tm t;
  291. t.tm_year =year -1900;
  292. t.tm_mon =month-1;
  293. t.tm_mday =day;
  294. t.tm_hour =hour;
  295. t.tm_min =minute;
  296. t.tm_sec =second;
  297. t.tm_wday =0;
  298. t.tm_yday =0;
  299. t.tm_isdst=-1; // -1 means data is unavailable
  300. {
  301. #if ANDROID && __ANDROID_API__<12 // since Android (<12) doesn't have built-in 'timegm' function, we had to write one which modifies time zones, because of that, calls to 'mktime' must be surrounded by locks
  302. SafeSyncLocker locker(mktime_lock);
  303. #endif
  304. time_t sec=mktime(&t); gmtime_r(&sec, &t);
  305. }
  306. year =t.tm_year+1900;
  307. month =t.tm_mon +1;
  308. day =t.tm_mday;
  309. hour =t.tm_hour;
  310. minute=t.tm_min;
  311. second=t.tm_sec;
  312. #endif
  313. }
  314. return T;
  315. }
  316. DateTime& DateTime::toLocal()
  317. {
  318. if(valid())
  319. {
  320. #if WINDOWS
  321. SYSTEMTIME utc, local;
  322. utc.wYear =year;
  323. utc.wMonth =month;
  324. utc.wDay =day;
  325. utc.wHour =hour;
  326. utc.wMinute=minute;
  327. utc.wSecond=second;
  328. utc.wDayOfWeek =0;
  329. utc.wMilliseconds=0;
  330. if(SystemTimeToTzSpecificLocalTime(null, &utc, &local))
  331. {
  332. year =local.wYear;
  333. month =local.wMonth;
  334. day =local.wDay;
  335. hour =local.wHour;
  336. minute=local.wMinute;
  337. second=local.wSecond;
  338. }
  339. #else
  340. tm t;
  341. t.tm_year =year -1900;
  342. t.tm_mon =month-1;
  343. t.tm_mday =day;
  344. t.tm_hour =hour;
  345. t.tm_min =minute;
  346. t.tm_sec =second;
  347. t.tm_wday =0;
  348. t.tm_yday =0;
  349. t.tm_isdst=-1; // -1 means data is unavailable
  350. time_t sec=timegm(&t); localtime_r(&sec, &t);
  351. year =t.tm_year+1900;
  352. month =t.tm_mon +1;
  353. day =t.tm_mday;
  354. hour =t.tm_hour;
  355. minute=t.tm_min;
  356. second=t.tm_sec;
  357. #endif
  358. }
  359. return T;
  360. }
  361. DateTime& DateTime::fromSeconds(Long s)
  362. {
  363. Int sec =s%(60*60*24),
  364. days=s/(60*60*24);
  365. second=sec%60; sec/=60;
  366. minute=sec%60; sec/=60;
  367. hour =sec ;
  368. year=400*(days/ 146097); // amount of days in 400 years (including days from leap years)
  369. days%=146097 ;
  370. if(days>=36525) // amount of days in first 100 years (including days from leap years)
  371. {
  372. year+=100; days-=36525;
  373. year+=100*(days/36524); days%=36524; // amount of days for each following 100 years (including days from leap years)
  374. }
  375. if(LeapYear(year))
  376. {
  377. year+=4*(days/ 1461); // amount of days in 4 years (including days from leap years)
  378. days%=1461 ;
  379. }else
  380. {
  381. if(days>=1460) // amount of days in first 4 years (without days from leap years) since first 4 years in non 100 leap year don't have leap days
  382. {
  383. year+=4; days-=1460;
  384. year+=4*(days/ 1461); // amount of days in each following 4 years (including days from leap years)
  385. days%=1461 ;
  386. }
  387. }
  388. if(LeapYear(year))
  389. {
  390. if(days>=366)
  391. {
  392. year++; days-=366;
  393. year+=days/ 365;
  394. days%=365;
  395. }
  396. }else
  397. {
  398. year+=days/ 365;
  399. days%=365;
  400. }
  401. month=1; REP(11){Int d=MonthDays(month, year); if(days>=d){month++; days-=d;}else break;}
  402. day =1+days;
  403. return T;
  404. }
  405. DateTime& DateTime::fromText(C Str &t)
  406. {
  407. Memt<Str> date_time; Split(date_time, t, ' ');
  408. if(date_time.elms()==2)
  409. {
  410. Memc<Str> date, time;
  411. Split(date, date_time[0], '-');
  412. Split(time, date_time[1], ':');
  413. if(date.elms()==3 && (time.elms()==2 || time.elms()==3))
  414. {
  415. year =TextInt(date[0]);
  416. month =TextInt(date[1]);
  417. day =TextInt(date[2]);
  418. hour =TextInt(time[0]);
  419. minute=TextInt(time[1]);
  420. second=((time.elms()==3) ? TextInt(time[2]) : 0);
  421. return T;
  422. }
  423. }
  424. return zero();
  425. }
  426. static const Long UnixSeconds=62167219200; // 62167219200 is the number of seconds at 1st Jan 1970
  427. Long DateTime :: seconds1970()C {return seconds()-UnixSeconds;}
  428. Long DateTimeMs::milliseconds1970()C {return seconds1970()*1000 + millisecond;}
  429. DateTime& DateTime::from1970s (ULong s) {return fromSeconds( s+UnixSeconds);}
  430. DateTime& DateTime::from1970ms(ULong ms) {return from1970s (ms/1000 );}
  431. DateTimeMs& DateTimeMs::fromSeconds( Long s) {T.millisecond= 0; super::fromSeconds( s ); return T;}
  432. DateTimeMs& DateTimeMs::from1970s (ULong s) {T.millisecond= 0; super::from1970s ( s ); return T;}
  433. DateTimeMs& DateTimeMs::from1970ms (ULong ms) {T.millisecond=ms%1000; super::from1970s (ms/1000); return T;}
  434. #if APPLE
  435. DateTime& DateTime::from(NSDate *date)
  436. {
  437. if(date)from1970s(TruncL([date timeIntervalSince1970]));else zero();
  438. return T;
  439. }
  440. #endif
  441. /******************************************************************************/
  442. Bool DateTime::save(File &f)C {f.putMulti(second, minute, hour, day, month, year); return f.ok();}
  443. Bool DateTime::load(File &f) {f.getMulti(second, minute, hour, day, month, year); if(f.ok())return true; zero(); return false;}
  444. /******************************************************************************/
  445. Int Compare(C DateTime &d0, C DateTime &d1)
  446. {
  447. Int d=d0.year -d1.year ; if(d<0)return -1; if(d>0)return +1;
  448. d=d0.month -d1.month ; if(d<0)return -1; if(d>0)return +1;
  449. d=d0.day -d1.day ; if(d<0)return -1; if(d>0)return +1;
  450. d=d0.hour -d1.hour ; if(d<0)return -1; if(d>0)return +1;
  451. d=d0.minute-d1.minute; if(d<0)return -1; if(d>0)return +1;
  452. d=d0.second-d1.second; if(d<0)return -1; if(d>0)return +1;
  453. return 0;
  454. }
  455. Int Compare(C DateTime &d0, C DateTime &d1, Int epsilon)
  456. {
  457. Long d=d0.seconds()-d1.seconds();
  458. if( d<-epsilon)return -1;
  459. if( d> epsilon)return +1;
  460. return 0;
  461. }
  462. Long operator+(C DateTime &d0, C DateTime &d1) {return d0.seconds()+d1.seconds();}
  463. Long operator-(C DateTime &d0, C DateTime &d1) {return d0.seconds()-d1.seconds();}
  464. /******************************************************************************/
  465. // MAIN
  466. /******************************************************************************/
  467. Bool LeapYear (Int year ) {return (!(year%4) && year%100) || !(year%400);}
  468. Int MonthDays(Int month ) {return (month>=1 && month<=12) ? _MonthDays[month-1] : -1;}
  469. Int MonthDays(Int month, Int year) {return (month==2 && LeapYear(year)) ? 29 : MonthDays(month);}
  470. CChar8* MonthNameShort(Int month) {return (month>=1 && month<=12) ? _MonthNameShort[month-1] : null;}
  471. CChar8* MonthName (Int month) {return (month>=1 && month<=12) ? _MonthName [month-1] : null;}
  472. static CChar8* YearName(TIME_NAME name, Int x)
  473. {
  474. switch(name)
  475. {
  476. default : return "y";
  477. case TIME_NAME_MED : case TIME_NAME_LONG : return (x==1) ? " year" : " years";
  478. case TIME_NAME_MED_UP: case TIME_NAME_LONG_UP: return (x==1) ? " Year" : " Years";
  479. }
  480. }
  481. static CChar8* SimpleMonthName(TIME_NAME name, Int x)
  482. {
  483. switch(name)
  484. {
  485. default : return "m";
  486. case TIME_NAME_MED : case TIME_NAME_LONG : return (x==1) ? " month" : " months";
  487. case TIME_NAME_MED_UP: case TIME_NAME_LONG_UP: return (x==1) ? " Month" : " Months";
  488. }
  489. }
  490. static CChar8* MonthName(TIME_NAME name, Int x)
  491. {
  492. switch(name)
  493. {
  494. default : return "mo";
  495. case TIME_NAME_MED : case TIME_NAME_LONG : return (x==1) ? " month" : " months";
  496. case TIME_NAME_MED_UP: case TIME_NAME_LONG_UP: return (x==1) ? " Month" : " Months";
  497. }
  498. }
  499. static CChar8* DayName(TIME_NAME name, Int x)
  500. {
  501. switch(name)
  502. {
  503. default : return "d";
  504. case TIME_NAME_MED : case TIME_NAME_LONG : return (x==1) ? " day" : " days";
  505. case TIME_NAME_MED_UP: case TIME_NAME_LONG_UP: return (x==1) ? " Day" : " Days";
  506. }
  507. }
  508. static CChar8* HourName(TIME_NAME name, Int x)
  509. {
  510. switch(name)
  511. {
  512. default : return "h";
  513. case TIME_NAME_MED : case TIME_NAME_LONG : return (x==1) ? " hour" : " hours";
  514. case TIME_NAME_MED_UP: case TIME_NAME_LONG_UP: return (x==1) ? " Hour" : " Hours";
  515. }
  516. }
  517. static CChar8* MinuteName(TIME_NAME name, Int x)
  518. {
  519. switch(name)
  520. {
  521. default : return "m";
  522. case TIME_NAME_MED : return " min";
  523. case TIME_NAME_MED_UP : return " Min";
  524. case TIME_NAME_LONG : return (x==1) ? " minute" : " minutes";
  525. case TIME_NAME_LONG_UP: return (x==1) ? " Minute" : " Minutes";
  526. }
  527. }
  528. static CChar8* SecondName(TIME_NAME name, Int x)
  529. {
  530. switch(name)
  531. {
  532. default : return "s";
  533. case TIME_NAME_MED : return " sec";
  534. case TIME_NAME_MED_UP : return " Sec";
  535. case TIME_NAME_LONG : return (x==1) ? " second" : " seconds";
  536. case TIME_NAME_LONG_UP: return (x==1) ? " Second" : " Seconds";
  537. }
  538. }
  539. Str TimeText(Long seconds, TIME_NAME name, Int parts)
  540. {
  541. Str str;
  542. if(parts)
  543. {
  544. const Int spy=31557600, // seconds per year = 365.25 days per year * 12 months * 24 hours * 60 minutes * 60 seconds
  545. spm=spy/12; // seconds per month
  546. if(seconds<0){CHS(seconds); str+='-';}
  547. Int y =seconds/spy, // years
  548. s =seconds%spy; // can be truncated to Int
  549. Int mo=s/spm; s%=spm;
  550. Int d =s/(60*60*24),
  551. h =s/(60*60 )%24,
  552. m =s/(60 )%60;
  553. s =s %60;
  554. Bool skip_empty=(parts<0); if(skip_empty)CHS(parts);
  555. if(y)
  556. {
  557. str+=y;
  558. str+=YearName(name, y);
  559. if(parts>=2 && (skip_empty ? mo : true))
  560. {
  561. str+=' ';
  562. str+=mo;
  563. str+=SimpleMonthName(name, mo);
  564. }
  565. }else
  566. if(mo)
  567. {
  568. str+=mo;
  569. str+=MonthName(name, mo);
  570. if(parts>=2 && (skip_empty ? d : true))
  571. {
  572. str+=' ';
  573. str+=d;
  574. str+=DayName(name, d);
  575. }
  576. }else
  577. if(d)
  578. {
  579. str+=d;
  580. str+=DayName(name, d);
  581. if(parts>=2 && (skip_empty ? h : true))
  582. {
  583. str+=' ';
  584. str+=h;
  585. str+=HourName(name, h);
  586. }
  587. }else
  588. if(h)
  589. {
  590. str+=h;
  591. str+=HourName(name, h);
  592. if(parts>=2 && (skip_empty ? m : true))
  593. {
  594. str+=' ';
  595. str+=m;
  596. str+=MinuteName(name, m);
  597. }
  598. }else
  599. if(m)
  600. {
  601. str+=m;
  602. str+=MinuteName(name, m);
  603. if(parts>=2 && (skip_empty ? s : true))
  604. {
  605. str+=' ';
  606. str+=s;
  607. str+=SecondName(name, s);
  608. }
  609. }else
  610. {
  611. str+=s;
  612. str+=SecondName(name, s);
  613. }
  614. }
  615. return str;
  616. }
  617. Str TimeTextHour(Long seconds, TIME_NAME name, Int parts)
  618. {
  619. Str str;
  620. if(parts)
  621. {
  622. if(seconds<0){CHS(seconds); str+='-';}
  623. Long h=seconds/(60*60);
  624. Int m=seconds/(60 )%60,
  625. s=seconds %60;
  626. Bool skip_empty=(parts<0); if(skip_empty)CHS(parts);
  627. if(h)
  628. {
  629. str+=h;
  630. str+=HourName(name, h);
  631. if(parts>=2 && (skip_empty ? m : true))
  632. {
  633. str+=' ';
  634. str+=m;
  635. str+=MinuteName(name, m);
  636. }
  637. }else
  638. if(m)
  639. {
  640. str+=m;
  641. str+=MinuteName(name, m);
  642. if(parts>=2 && (skip_empty ? s : true))
  643. {
  644. str+=' ';
  645. str+=s;
  646. str+=SecondName(name, s);
  647. }
  648. }else
  649. {
  650. str+=s;
  651. str+=SecondName(name, s);
  652. }
  653. }
  654. return str;
  655. }
  656. /******************************************************************************/
  657. }
  658. /******************************************************************************/