14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * Glenn Fowler 254887Schin * AT&T Research 264887Schin * 274887Schin * time conversion support 284887Schin */ 294887Schin 304887Schin #include <ast.h> 3110898Sroland.mainz@nrubsig.org #include <tmx.h> 324887Schin 334887Schin #define DAYS(p) (tm_data.days[(p)->tm_mon]+((p)->tm_mon==1&&LEAP(p))) 344887Schin #define LEAP(p) (tmisleapyear((p)->tm_year)) 354887Schin 364887Schin /* 374887Schin * correct out of bounds fields in tm 384887Schin * 3910898Sroland.mainz@nrubsig.org * tm_isdst is not changed -- call tmxtm() to get that 404887Schin * 414887Schin * tm is the return value 424887Schin */ 434887Schin 444887Schin Tm_t* tmfix(register Tm_t * tm)454887Schintmfix(register Tm_t* tm) 464887Schin { 474887Schin register int n; 484887Schin register int w; 494887Schin Tm_t* p; 504887Schin time_t t; 514887Schin 524887Schin /* 534887Schin * check for special case that adjusts tm_wday at the end 544887Schin * this happens during 554887Schin * nl_langinfo() => strftime() => tmfmt() 564887Schin */ 574887Schin 584887Schin if (w = !tm->tm_sec && !tm->tm_min && !tm->tm_mday && !tm->tm_year && !tm->tm_yday && !tm->tm_isdst) 594887Schin { 604887Schin tm->tm_year = 99; 614887Schin tm->tm_mday = 2; 624887Schin } 634887Schin 644887Schin /* 654887Schin * adjust from shortest to longest units 664887Schin */ 674887Schin 6810898Sroland.mainz@nrubsig.org if ((n = tm->tm_nsec) < 0) 6910898Sroland.mainz@nrubsig.org { 7010898Sroland.mainz@nrubsig.org tm->tm_sec -= (TMX_RESOLUTION - n) / TMX_RESOLUTION; 7110898Sroland.mainz@nrubsig.org tm->tm_nsec = TMX_RESOLUTION - (-n) % TMX_RESOLUTION; 7210898Sroland.mainz@nrubsig.org } 7310898Sroland.mainz@nrubsig.org else if (n >= TMX_RESOLUTION) 7410898Sroland.mainz@nrubsig.org { 7510898Sroland.mainz@nrubsig.org tm->tm_sec += n / TMX_RESOLUTION; 7610898Sroland.mainz@nrubsig.org tm->tm_nsec %= TMX_RESOLUTION; 7710898Sroland.mainz@nrubsig.org } 784887Schin if ((n = tm->tm_sec) < 0) 794887Schin { 804887Schin tm->tm_min -= (60 - n) / 60; 814887Schin tm->tm_sec = 60 - (-n) % 60; 824887Schin } 834887Schin else if (n > (59 + TM_MAXLEAP)) 844887Schin { 854887Schin tm->tm_min += n / 60; 864887Schin tm->tm_sec %= 60; 874887Schin } 884887Schin if ((n = tm->tm_min) < 0) 894887Schin { 904887Schin tm->tm_hour -= (60 - n) / 60; 914887Schin n = tm->tm_min = 60 - (-n) % 60; 924887Schin } 934887Schin if (n > 59) 944887Schin { 954887Schin tm->tm_hour += n / 60; 964887Schin tm->tm_min %= 60; 974887Schin } 984887Schin if ((n = tm->tm_hour) < 0) 994887Schin { 1004887Schin tm->tm_mday -= (23 - n) / 24; 1014887Schin tm->tm_hour = 24 - (-n) % 24; 1024887Schin } 1034887Schin else if (n >= 24) 1044887Schin { 1054887Schin tm->tm_mday += n / 24; 1064887Schin tm->tm_hour %= 24; 1074887Schin } 1084887Schin if (tm->tm_mon >= 12) 1094887Schin { 1104887Schin tm->tm_year += tm->tm_mon / 12; 1114887Schin tm->tm_mon %= 12; 1124887Schin } 1134887Schin else if (tm->tm_mon < 0) 1144887Schin { 1154887Schin tm->tm_year--; 1164887Schin if ((tm->tm_mon += 12) < 0) 1174887Schin { 1184887Schin tm->tm_year += tm->tm_mon / 12; 1194887Schin tm->tm_mon = (-tm->tm_mon) % 12; 1204887Schin } 1214887Schin } 1224887Schin while (tm->tm_mday < -365) 1234887Schin { 1244887Schin tm->tm_year--; 1254887Schin tm->tm_mday += 365 + LEAP(tm); 1264887Schin } 1274887Schin while (tm->tm_mday > 365) 1284887Schin { 1294887Schin tm->tm_mday -= 365 + LEAP(tm); 1304887Schin tm->tm_year++; 1314887Schin } 1324887Schin while (tm->tm_mday < 1) 1334887Schin { 1344887Schin if (--tm->tm_mon < 0) 1354887Schin { 1364887Schin tm->tm_mon = 11; 1374887Schin tm->tm_year--; 1384887Schin } 1394887Schin tm->tm_mday += DAYS(tm); 1404887Schin } 1414887Schin while (tm->tm_mday > (n = DAYS(tm))) 1424887Schin { 1434887Schin tm->tm_mday -= n; 1444887Schin if (++tm->tm_mon > 11) 1454887Schin { 1464887Schin tm->tm_mon = 0; 1474887Schin tm->tm_year++; 1484887Schin } 1494887Schin } 1504887Schin if (w) 1514887Schin { 1524887Schin w = tm->tm_wday; 1534887Schin t = tmtime(tm, TM_LOCALZONE); 1544887Schin p = tmmake(&t); 1554887Schin if (w = (w - p->tm_wday)) 1564887Schin { 1574887Schin if (w < 0) 1584887Schin w += 7; 1594887Schin tm->tm_wday += w; 1604887Schin if ((tm->tm_mday += w) > DAYS(tm)) 1614887Schin tm->tm_mday -= 7; 1624887Schin } 1634887Schin } 1644887Schin tm->tm_yday = tm_data.sum[tm->tm_mon] + (tm->tm_mon > 1 && LEAP(tm)) + tm->tm_mday - 1; 1654887Schin n = tm->tm_year + 1900 - 1; 1664887Schin tm->tm_wday = (n + n / 4 - n / 100 + n / 400 + tm->tm_yday + 1) % 7; 1674887Schin 1684887Schin /* 1694887Schin * tm_isdst is adjusted by tmtime() 1704887Schin */ 1714887Schin 1724887Schin return tm; 1734887Schin } 174