PostgreSQL Source Code: src/timezone/strftime.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

42

43#include <fcntl.h>

44

46

47

49{

57 const char *am;

58 const char *pm;

60};

61

62#define Locale (&C_time_locale)

63

65 {

66 "Jan", "Feb", "Mar", "Apr", "May", "Jun",

67 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"

68 }, {

69 "January", "February", "March", "April", "May", "June",

70 "July", "August", "September", "October", "November", "December"

71 }, {

72 "Sun", "Mon", "Tue", "Wed",

73 "Thu", "Fri", "Sat"

74 }, {

75 "Sunday", "Monday", "Tuesday", "Wednesday",

76 "Thursday", "Friday", "Saturday"

77 },

78

79

80 "%H:%M:%S",

81

82

83

84

85

86

87

88 "%m/%d/%y",

89

90

91

92

93

94

95

96

97 "%a %b %e %T %Y",

98

99

100 "AM",

101

102

103 "PM",

104

105

106 "%a %b %e %H:%M:%S %Z %Y"

107};

108

110{

113

114static char *_add(const char *str, char *pt, const char *ptlim);

115static char *_conv(int n, const char *format, char *pt, const char *ptlim);

116static char *_fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,

117 enum warn *warnp);

118static char *_yconv(int a, int b, bool convert_top, bool convert_yy, char *pt, char const *ptlim);

119

120

121

122

123

124

125

126

127size_t

129{

130 char *p;

131 int saved_errno = errno;

133

135 if (!p)

136 {

138 return 0;

139 }

140 if (p == s + maxsize)

141 {

142 errno = ERANGE;

143 return 0;

144 }

145 *p = '\0';

146 errno = saved_errno;

147 return p - s;

148}

149

150static char *

152 const char *ptlim, enum warn *warnp)

153{

155 {

157 {

160 {

161 case '\0':

163 break;

164 case 'A':

168 pt, ptlim);

169 continue;

170 case 'a':

174 pt, ptlim);

175 continue;

176 case 'B':

180 pt, ptlim);

181 continue;

182 case 'b':

183 case 'h':

187 pt, ptlim);

188 continue;

189 case 'C':

190

191

192

193

194

195

197 true, false, pt, ptlim);

198 continue;

199 case 'c':

200 {

202

203 pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);

206 if (warn2 > *warnp)

207 *warnp = warn2;

208 }

209 continue;

210 case 'D':

211 pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);

212 continue;

213 case 'd':

215 continue;

216 case 'E':

217 case 'O':

218

219

220

221

222

223

224

226 case 'e':

228 continue;

229 case 'F':

230 pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);

231 continue;

232 case 'H':

234 continue;

235 case 'I':

238 "%02d", pt, ptlim);

239 continue;

240 case 'j':

241 pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);

242 continue;

243 case 'k':

244

245

246

247

248

249

250

251

253 continue;

254#ifdef KITCHEN_SINK

255 case 'K':

256

257

258

259

260 pt = _add("kitchen sink", pt, ptlim);

261 continue;

262#endif

263 case 'l':

264

265

266

267

268

269

270

273 "%2d", pt, ptlim);

274 continue;

275 case 'M':

276 pt = _conv(t->tm_min, "%02d", pt, ptlim);

277 continue;

278 case 'm':

279 pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);

280 continue;

281 case 'n':

282 pt = _add("\n", pt, ptlim);

283 continue;

284 case 'p':

288 pt, ptlim);

289 continue;

290 case 'R':

291 pt = _fmt("%H:%M", t, pt, ptlim, warnp);

292 continue;

293 case 'r':

294 pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);

295 continue;

296 case 'S':

297 pt = _conv(t->tm_sec, "%02d", pt, ptlim);

298 continue;

299 case 'T':

300 pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);

301 continue;

302 case 't':

303 pt = _add("\t", pt, ptlim);

304 continue;

305 case 'U':

308 "%02d", pt, ptlim);

309 continue;

310 case 'u':

311

312

313

314

315

316

319 "%d", pt, ptlim);

320 continue;

321 case 'V':

322 case 'G':

323 case 'g':

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342 {

343 int year;

344 int base;

345 int yday;

347 int w;

348

353 for (;;)

354 {

356 int bot;

357 int top;

358

362

363

364

365

366

367 bot = ((yday + 11 - wday) %

369

370

371

372

373 top = bot -

375 if (top < -3)

377 top += len;

378 if (yday >= top)

379 {

380 ++base;

381 w = 1;

382 break;

383 }

384 if (yday >= bot)

385 {

386 w = 1 + ((yday - bot) /

388 break;

389 }

390 --base;

394 }

396 pt = _conv(w, "%02d",

397 pt, ptlim);

398 else if (*format == 'g')

399 {

401 pt = _yconv(year, base,

402 false, true,

403 pt, ptlim);

404 }

405 else

406 pt = _yconv(year, base,

407 true, true,

408 pt, ptlim);

409 }

410 continue;

411 case 'v':

412

413

414

415

416

417 pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);

418 continue;

419 case 'W':

424 "%02d", pt, ptlim);

425 continue;

426 case 'w':

428 continue;

429 case 'X':

430 pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);

431 continue;

432 case 'x':

433 {

435

436 pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);

439 if (warn2 > *warnp)

440 *warnp = warn2;

441 }

442 continue;

443 case 'y':

446 false, true,

447 pt, ptlim);

448 continue;

449 case 'Y':

451 true, true,

452 pt, ptlim);

453 continue;

454 case 'Z':

457

458

459

460

461

462

463 continue;

464 case 'z':

465 {

466 long diff;

467 char const *sign;

468 bool negative;

469

471 continue;

473 negative = diff < 0;

474 if (diff == 0)

475 {

477 negative = t->tm_zone[0] == '-';

478 }

479 if (negative)

480 {

482 diff = -diff;

483 }

484 else

490 pt = _conv(diff, "%04d", pt, ptlim);

491 }

492 continue;

493 case '+':

494 pt = _fmt(Locale->date_fmt, t, pt, ptlim,

495 warnp);

496 continue;

497 case '%':

498

499

500

501

502

503

504 default:

505 break;

506 }

507 }

508 if (pt == ptlim)

509 break;

511 }

512 return pt;

513}

514

515static char *

516_conv(int n, const char *format, char *pt, const char *ptlim)

517{

519

521 return _add(buf, pt, ptlim);

522}

523

524static char *

525_add(const char *str, char *pt, const char *ptlim)

526{

527 while (pt < ptlim && (*pt = *str++) != '\0')

528 ++pt;

529 return pt;

530}

531

532

533

534

535

536

537

538

539

540static char *

541_yconv(int a, int b, bool convert_top, bool convert_yy,

542 char *pt, const char *ptlim)

543{

544 int lead;

545 int trail;

546

547#define DIVISOR 100

551 if (trail < 0 && lead > 0)

552 {

554 --lead;

555 }

556 else if (lead < 0 && trail > 0)

557 {

559 ++lead;

560 }

561 if (convert_top)

562 {

563 if (lead == 0 && trail < 0)

564 pt = _add("-0", pt, ptlim);

565 else

566 pt = _conv(lead, "%02d", pt, ptlim);

567 }

568 if (convert_yy)

569 pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);

570 return pt;

571}

#define INT_STRLEN_MAXIMUM(type)

static char * _add(const char *str, char *pt, const char *ptlim)

static char * _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim, enum warn *warnp)

static char * _yconv(int a, int b, bool convert_top, bool convert_yy, char *pt, char const *ptlim)

static char * _conv(int n, const char *format, char *pt, const char *ptlim)

size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)

static const struct lc_time_T C_time_locale

const char * mon[MONSPERYEAR]

const char * weekday[DAYSPERWEEK]

const char * wday[DAYSPERWEEK]

const char * month[MONSPERYEAR]