Newer
Older
Tilghman Lesher
committed
if (format == NULL)
format = "AdBY 'digits/at' IMp";
ast_localtime(&time,&tm,timezone);
for (offset=0 ; format[offset] != '\0' ; offset++) {
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
switch (format[offset]) {
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
case '\'':
/* Literal name of a sound file */
sndoffset=0;
for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
sndfile[sndoffset] = format[offset];
sndfile[sndoffset] = '\0';
res = wait_file(chan,ints,sndfile,lang);
break;
case 'A':
case 'a':
/* Sunday - Saturday */
snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'B':
case 'b':
case 'h':
/* January - December */
snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
res = wait_file(chan,ints,nextmsg,lang);
break;
Mark Spencer
committed
case 'm':
/* First - Twelfth */
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'd':
case 'e':
Mark Spencer
committed
/* First */
if (tm.tm_mday == 1) {
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
res = wait_file(chan,ints,nextmsg,lang);
} else {
Mark Spencer
committed
res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
}
break;
case 'Y':
/* Year */
if (tm.tm_year > 99) {
Mark Spencer
committed
res = wait_file(chan,ints, "digits/2",lang);
if (!res) {
res = wait_file(chan,ints, "digits/thousand",lang);
}
if (tm.tm_year > 100) {
if (!res) {
res = ast_say_number(chan, tm.tm_year - 100, ints, lang, (char * ) NULL);
}
}
} else {
if (tm.tm_year < 1) {
/* I'm not going to handle 1900 and prior */
/* We'll just be silent on the year, instead of bombing out. */
} else {
res = wait_file(chan,ints, "digits/thousand",lang);
if (!res) {
wait_file(chan,ints, "digits/9",lang);
wait_file(chan,ints, "digits/hundred",lang);
Mark Spencer
committed
res = ast_say_number(chan, tm.tm_year, ints, lang, (char * ) NULL);
}
}
}
break;
case 'I':
case 'l':
/* 12-Hour */
if (tm.tm_hour == 0)
snprintf(nextmsg,sizeof(nextmsg), "digits/12");
else if (tm.tm_hour > 12)
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
else
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
res = wait_file(chan,ints,nextmsg,lang);
if (!res)
res = wait_file(chan,ints, "digits/oclock",lang);
break;
case 'H':
case 'k':
/* 24-Hour */
Mark Spencer
committed
res = ast_say_number(chan, tm.tm_hour, ints, lang, (char * ) NULL);
if (!res)
res = wait_file(chan,ints, "digits/oclock",lang);
break;
case 'M':
/* Minute */
if (tm.tm_min == 0) {
break;
}
res = ast_say_number(chan, tm.tm_min, ints, lang, (char * ) NULL);
break;
case 'P':
case 'p':
/* AM/PM */
if (tm.tm_hour > 11)
snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
else
snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'Q':
Mark Spencer
committed
/* Shorthand for "Today", "Yesterday", or AdBY */
Tilghman Lesher
committed
/* XXX As emphasized elsewhere, this should the native way in your
* language to say the date, with changes in what you say, depending
* upon how recent the date is. XXX */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
res = wait_file(chan,ints, "digits/today",lang);
} else if (beg_today - 86400 < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else {
Tilghman Lesher
committed
res = ast_say_date_with_format_fr(chan, time, ints, lang, "AdBY", timezone);
}
}
break;
case 'q':
Mark Spencer
committed
/* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
Tilghman Lesher
committed
/* XXX As emphasized elsewhere, this should the native way in your
* language to say the date, with changes in what you say, depending
* upon how recent the date is. XXX */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
} else if ((beg_today - 86400) < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else if (beg_today - 86400 * 6 < time) {
/* Within the last week */
Tilghman Lesher
committed
res = ast_say_date_with_format_fr(chan, time, ints, lang, "A", timezone);
} else {
Tilghman Lesher
committed
res = ast_say_date_with_format_fr(chan, time, ints, lang, "AdBY", timezone);
}
}
break;
case 'R':
Tilghman Lesher
committed
res = ast_say_date_with_format_fr(chan, time, ints, lang, "HM", timezone);
break;
case 'S':
/* Seconds */
Mark Spencer
committed
res = ast_say_number(chan, tm.tm_hour, ints, lang, (char * ) NULL);
if (!res) {
res = wait_file(chan,ints, "digits/second",lang);
}
break;
case 'T':
Tilghman Lesher
committed
res = ast_say_date_with_format_fr(chan, time, ints, lang, "HMS", timezone);
break;
case ' ':
case ' ':
/* Just ignore spaces and tabs */
break;
default:
/* Unknown character */
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
}
/* Jump out on DTMF */
if (res) {
break;
}
}
return res;
}
Mark Spencer
committed
int ast_say_date_with_format_it(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
{
struct tm tm;
int res=0, offset, sndoffset;
char sndfile[256], nextmsg[256];
Tilghman Lesher
committed
if (format == NULL)
format = "AdB 'digits/at' IMp";
ast_localtime(&time,&tm,timezone);
for (offset=0 ; format[offset] != '\0' ; offset++) {
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
switch (format[offset]) {
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
case '\'':
/* Literal name of a sound file */
sndoffset=0;
for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
Mark Spencer
committed
sndfile[sndoffset] = format[offset];
sndfile[sndoffset] = '\0';
Mark Spencer
committed
res = wait_file(chan,ints,sndfile,lang);
break;
case 'A':
case 'a':
/* Sunday - Saturday */
snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'B':
case 'b':
case 'h':
/* January - December */
snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
res = wait_file(chan,ints,nextmsg,lang);
break;
Mark Spencer
committed
case 'm':
/* First - Twelfth */
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'd':
case 'e':
Mark Spencer
committed
/* First day of the month is spelled as ordinal */
if (tm.tm_mday == 1) {
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
res = wait_file(chan,ints,nextmsg,lang);
} else {
if (!res) {
res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
}
}
break;
case 'Y':
/* Year */
Mark Spencer
committed
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
if (tm.tm_year > 99) {
res = wait_file(chan,ints, "digits/ore-2000",lang);
if (tm.tm_year > 100) {
if (!res) {
/* This works until the end of 2021 */
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
res = wait_file(chan,ints,nextmsg,lang);
}
}
} else {
if (tm.tm_year < 1) {
/* I'm not going to handle 1900 and prior */
/* We'll just be silent on the year, instead of bombing out. */
} else {
res = wait_file(chan,ints, "digits/ore-1900",lang);
if ((!res) && (tm.tm_year != 0)) {
if (tm.tm_year <= 21) {
/* 1910 - 1921 */
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
res = wait_file(chan,ints,nextmsg,lang);
} else {
/* 1922 - 1999, but sounds badly in 1928, 1931, 1938, etc... */
int ten, one;
ten = tm.tm_year / 10;
one = tm.tm_year % 10;
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
res = wait_file(chan,ints,nextmsg,lang);
if (!res) {
if (one != 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
res = wait_file(chan,ints,nextmsg,lang);
}
}
}
}
}
}
break;
case 'I':
case 'l':
/* 12-Hour */
if (tm.tm_hour == 0)
snprintf(nextmsg,sizeof(nextmsg), "digits/12");
else if (tm.tm_hour > 12)
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
else
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
Mark Spencer
committed
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'H':
case 'k':
/* 24-Hour */
Mark Spencer
committed
if (tm.tm_hour == 0) {
res = wait_file(chan,ints, "digits/ore-mezzanotte",lang);
} else if (tm.tm_hour == 1) {
res = wait_file(chan,ints, "digits/ore-una",lang);
} else {
res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
}
case 'M':
/* Minute */
Mark Spencer
committed
res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
break;
case 'P':
case 'p':
/* AM/PM */
Mark Spencer
committed
if (tm.tm_hour > 11)
snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
else
snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'Q':
/* Shorthand for "Today", "Yesterday", or ABdY */
Tilghman Lesher
committed
/* XXX As emphasized elsewhere, this should the native way in your
* language to say the date, with changes in what you say, depending
* upon how recent the date is. XXX */
Kevin P. Fleming
committed
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
Mark Spencer
committed
Kevin P. Fleming
committed
gettimeofday(&now,NULL);
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
res = wait_file(chan,ints, "digits/today",lang);
} else if (beg_today - 86400 < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else {
Tilghman Lesher
committed
res = ast_say_date_with_format_it(chan, time, ints, lang, "AdB", timezone);
}
}
break;
case 'q':
/* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
Mark Spencer
committed
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
} else if ((beg_today - 86400) < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else if (beg_today - 86400 * 6 < time) {
/* Within the last week */
Tilghman Lesher
committed
res = ast_say_date_with_format_it(chan, time, ints, lang, "A", timezone);
Tilghman Lesher
committed
res = ast_say_date_with_format_it(chan, time, ints, lang, "AdB", timezone);
}
}
break;
case 'R':
Tilghman Lesher
committed
res = ast_say_date_with_format_it(chan, time, ints, lang, "HM", timezone);
Mark Spencer
committed
break;
case 'S':
/* Seconds */
if (tm.tm_sec == 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
} else if (tm.tm_sec < 10) {
res = wait_file(chan,ints, "digits/oh",lang);
if (!res) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
}
} else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
} else {
int ten, one;
ten = (tm.tm_sec / 10) * 10;
one = (tm.tm_sec % 10);
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
res = wait_file(chan,ints,nextmsg,lang);
if (!res) {
/* Fifty, not fifty-zero */
if (one != 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
res = wait_file(chan,ints,nextmsg,lang);
}
}
}
Mark Spencer
committed
break;
case 'T':
Tilghman Lesher
committed
res = ast_say_date_with_format_it(chan, time, ints, lang, "HMS", timezone);
break;
case ' ':
case ' ':
/* Just ignore spaces and tabs */
break;
default:
/* Unknown character */
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
}
/* Jump out on DTMF */
if (res) {
break;
}
}
return res;
}
/* Dutch syntax */
Mark Spencer
committed
int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
{
struct tm tm;
int res=0, offset, sndoffset;
char sndfile[256], nextmsg[256];
Tilghman Lesher
committed
if (format == NULL)
format = "ABdY 'digits/at' IMp";
ast_localtime(&time,&tm,timezone);
for (offset=0 ; format[offset] != '\0' ; offset++) {
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
switch (format[offset]) {
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
case '\'':
/* Literal name of a sound file */
sndoffset=0;
for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
sndfile[sndoffset] = format[offset];
sndfile[sndoffset] = '\0';
res = wait_file(chan,ints,sndfile,lang);
break;
case 'A':
case 'a':
/* Sunday - Saturday */
snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'B':
case 'b':
case 'h':
/* January - December */
snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
res = wait_file(chan,ints,nextmsg,lang);
break;
Mark Spencer
committed
case 'm':
/* First - Twelfth */
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
res = wait_file(chan,ints,nextmsg,lang);
break;
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
case 'd':
case 'e':
/* First - Thirtyfirst */
res = ast_say_number(chan, tm.tm_mday, ints, lang, NULL);
break;
case 'Y':
/* Year */
if (tm.tm_year > 99) {
res = wait_file(chan,ints, "digits/2",lang);
if (!res) {
res = wait_file(chan,ints, "digits/thousand",lang);
}
if (tm.tm_year > 100) {
if (!res) {
/* This works until the end of 2020 */
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
res = wait_file(chan,ints,nextmsg,lang);
}
}
} else {
if (tm.tm_year < 1) {
/* I'm not going to handle 1900 and prior */
/* We'll just be silent on the year, instead of bombing out. */
} else {
res = wait_file(chan,ints, "digits/19",lang);
if (!res) {
if (tm.tm_year <= 9) {
/* 1901 - 1909 */
res = wait_file(chan,ints, "digits/oh",lang);
if (!res) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
res = wait_file(chan,ints,nextmsg,lang);
}
} else if (tm.tm_year <= 20) {
/* 1910 - 1920 */
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
res = wait_file(chan,ints,nextmsg,lang);
} else {
/* 1921 - 1999 */
int ten, one;
ten = tm.tm_year / 10;
one = tm.tm_year % 10;
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
res = wait_file(chan,ints,nextmsg,lang);
if (!res) {
if (one != 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
res = wait_file(chan,ints,nextmsg,lang);
}
}
}
}
}
}
break;
case 'I':
case 'l':
/* 12-Hour */
if (tm.tm_hour == 0)
snprintf(nextmsg,sizeof(nextmsg), "digits/12");
else if (tm.tm_hour > 12)
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
else
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'H':
case 'k':
/* 24-Hour */
res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
if (!res) {
res = wait_file(chan,ints, "digits/nl-uur",lang);
}
break;
case 'M':
/* Minute */
res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
break;
case 'P':
case 'p':
/* AM/PM */
if (tm.tm_hour > 11)
snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
else
snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'Q':
/* Shorthand for "Today", "Yesterday", or ABdY */
Tilghman Lesher
committed
/* XXX As emphasized elsewhere, this should the native way in your
* language to say the date, with changes in what you say, depending
* upon how recent the date is. XXX */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
res = wait_file(chan,ints, "digits/today",lang);
} else if (beg_today - 86400 < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else {
Tilghman Lesher
committed
res = ast_say_date_with_format_nl(chan, time, ints, lang, "ABdY", timezone);
}
}
break;
case 'q':
/* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
Kevin P. Fleming
committed
beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < time) {
/* Today */
} else if ((beg_today - 86400) < time) {
/* Yesterday */
res = wait_file(chan,ints, "digits/yesterday",lang);
} else if (beg_today - 86400 * 6 < time) {
/* Within the last week */
Tilghman Lesher
committed
res = ast_say_date_with_format_nl(chan, time, ints, lang, "A", timezone);
} else {
Tilghman Lesher
committed
res = ast_say_date_with_format_nl(chan, time, ints, lang, "ABdY", timezone);
}
}
break;
case 'R':
Tilghman Lesher
committed
res = ast_say_date_with_format_nl(chan, time, ints, lang, "HM", timezone);
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
break;
case 'S':
/* Seconds */
if (tm.tm_sec == 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
} else if (tm.tm_sec < 10) {
res = wait_file(chan,ints, "digits/oh",lang);
if (!res) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
}
} else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
res = wait_file(chan,ints,nextmsg,lang);
} else {
int ten, one;
ten = (tm.tm_sec / 10) * 10;
one = (tm.tm_sec % 10);
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
res = wait_file(chan,ints,nextmsg,lang);
if (!res) {
/* Fifty, not fifty-zero */
if (one != 0) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
res = wait_file(chan,ints,nextmsg,lang);
}
}
}
break;
case 'T':
Tilghman Lesher
committed
res = ast_say_date_with_format_nl(chan, time, ints, lang, "HMS", timezone);
break;
case ' ':
case ' ':
/* Just ignore spaces and tabs */
break;
default:
/* Unknown character */
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
}
/* Jump out on DTMF */
if (res) {
break;
}
}
return res;
}
Russell Bryant
committed
/* Polish syntax */
int ast_say_date_with_format_pl(struct ast_channel *chan, time_t thetime, const char *ints, const char *lang, const char *format, const char *timezone)
Russell Bryant
committed
{
struct tm tm;
int res=0, offset, sndoffset;
char sndfile[256], nextmsg[256];
ast_localtime(&thetime, &tm, timezone);
Russell Bryant
committed
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
for (offset = 0 ; format[offset] != '\0' ; offset++) {
int remainder;
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
switch (format[offset]) {
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
case '\'':
/* Literal name of a sound file */
sndoffset = 0;
for (sndoffset = 0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
sndfile[sndoffset] = format[offset];
sndfile[sndoffset] = '\0';
res = wait_file(chan, ints, sndfile, lang);
break;
case 'A':
case 'a':
/* Sunday - Saturday */
snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
res = wait_file(chan, ints, nextmsg, lang);
break;
case 'B':
case 'b':
case 'h':
/* January - December */
snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
res = wait_file(chan, ints, nextmsg, lang);
break;
case 'm':
/* Month enumerated */
res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, NULL);
break;
case 'd':
case 'e':
/* First - Thirtyfirst */
remainder = tm.tm_mday;
if (tm.tm_mday > 20) {
res = wait_file(chan, ints, "digits/h-20", lang);
remainder -= 20;
}
if (!res) {
snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", remainder);
res = wait_file(chan, ints, nextmsg, lang);
}
break;
case 'Y':
/* Year */
if (tm.tm_year > 100) {
res = wait_file(chan, ints, "digits/2", lang);
if (!res)
res = wait_file(chan, ints, "digits/1000.2",lang);
if (tm.tm_year > 100) {
if (!res)
res = ast_say_enumeration(chan, tm.tm_year - 100, ints, lang, NULL);
}
} else if (tm.tm_year == 100) {
res = wait_file(chan, ints, "digits/h-2000", lang);
} else {
if (tm.tm_year < 1) {
/* I'm not going to handle 1900 and prior */
/* We'll just be silent on the year, instead of bombing out. */
break;
} else {
res = wait_file(chan, ints, "digits/1000", lang);
if (!res) {
wait_file(chan, ints, "digits/900", lang);
res = ast_say_enumeration(chan, tm.tm_year, ints, lang, NULL);
}
}
}
if (!res)
wait_file(chan, ints, "digits/year", lang);
break;
case 'I':
case 'l':
/* 12-Hour */
if (tm.tm_hour == 0)
snprintf(nextmsg, sizeof(nextmsg), "digits/t-12");
else if (tm.tm_hour > 12)
snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour - 12);
else
snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
res = wait_file(chan, ints, nextmsg, lang);
break;
case 'H':
case 'k':
/* 24-Hour */
if (tm.tm_hour != 0) {
snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
res = wait_file(chan, ints, nextmsg, lang);
} else
res = wait_file(chan, ints, "digits/t-24", lang);
break;
case 'M':
case 'N':
/* Minute */
if (tm.tm_min == 0) {
if (format[offset] == 'M') {
res = wait_file(chan, ints, "digits/oclock", lang);
} else {
res = wait_file(chan, ints, "digits/100", lang);
}
} else
res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
break;
case 'P':
case 'p':
/* AM/PM */
if (tm.tm_hour > 11)
snprintf(nextmsg, sizeof(nextmsg), "digits/p-m");
else
snprintf(nextmsg, sizeof(nextmsg), "digits/a-m");
res = wait_file(chan, ints, nextmsg, lang);
break;
case 'Q':
/* Shorthand for "Today", "Yesterday", or AdBY */
{
time_t tv_sec = time(NULL);
Russell Bryant
committed
struct tm tmnow;
time_t beg_today;
ast_localtime(&tv_sec,&tmnow, timezone);
Russell Bryant
committed
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
beg_today = tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < thetime) {
Russell Bryant
committed
/* Today */
res = wait_file(chan, ints, "digits/today", lang);
} else if (beg_today - 86400 < thetime) {
Russell Bryant
committed
/* Yesterday */
res = wait_file(chan, ints, "digits/yesterday", lang);
} else {
res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", timezone);
Russell Bryant
committed
}
}
break;
case 'q':
/* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
{
time_t tv_sec = time(NULL);
Russell Bryant
committed
struct tm tmnow;
time_t beg_today;
ast_localtime(&tv_sec, &tmnow, timezone);
Russell Bryant
committed
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */
beg_today = tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
if (beg_today < thetime) {
Russell Bryant
committed
/* Today */
} else if ((beg_today - 86400) < thetime) {
Russell Bryant
committed
/* Yesterday */
res = wait_file(chan, ints, "digits/yesterday", lang);
} else if (beg_today - 86400 * 6 < thetime) {
Russell Bryant
committed
/* Within the last week */
res = ast_say_date_with_format(chan, thetime, ints, lang, "A", timezone);
Russell Bryant
committed
} else {
res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", timezone);
Russell Bryant
committed
}
}
break;
case 'R':
res = ast_say_date_with_format(chan, thetime, ints, lang, "HM", timezone);
Russell Bryant
committed
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
break;
case 'S':
/* Seconds */
res = wait_file(chan, ints, "digits/and", lang);
if (!res) {
if (tm.tm_sec == 1) {
res = wait_file(chan, ints, "digits/1z", lang);
if (!res)
res = wait_file(chan, ints, "digits/second-a", lang);
} else {
res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
if (!res) {
int ten, one;
ten = tm.tm_sec / 10;
one = tm.tm_sec % 10;
if (one > 1 && one < 5 && ten != 1)
res = wait_file(chan,ints, "digits/seconds",lang);
else
res = wait_file(chan,ints, "digits/second",lang);
}
}
}
break;
case 'T':
res = ast_say_date_with_format(chan, thetime, ints, lang, "HMS", timezone);
Russell Bryant
committed
break;
case ' ':
case ' ':
/* Just ignore spaces and tabs */
break;
default:
/* Unknown character */
ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
}
/* Jump out on DTMF */
if (res)
break;
}
return res;
}
/* Portuguese syntax */
Mark Spencer
committed
int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
{
struct tm tm;
int res=0, offset, sndoffset;
char sndfile[256], nextmsg[256];
Tilghman Lesher
committed
if (format == NULL)
format = "Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/at' IMp";
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
ast_localtime(&time,&tm,timezone);
for (offset=0 ; format[offset] != '\0' ; offset++) {
ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
switch (format[offset]) {
/* NOTE: if you add more options here, please try to be consistent with strftime(3) */
case '\'':
/* Literal name of a sound file */
sndoffset=0;
for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
sndfile[sndoffset] = format[offset];
sndfile[sndoffset] = '\0';
snprintf(nextmsg,sizeof(nextmsg), "%s", sndfile);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'A':
case 'a':
/* Sunday - Saturday */
snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'B':
case 'b':
case 'h':
/* January - December */
snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
res = wait_file(chan,ints,nextmsg,lang);
break;
Mark Spencer
committed
case 'm':
/* First - Twelfth */
snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
res = wait_file(chan,ints,nextmsg,lang);
break;
case 'd':
case 'e':
/* First - Thirtyfirst */
res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
break;
case 'Y':
/* Year */
res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
break;
case 'I':
case 'l':
/* 12-Hour */
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
if (tm.tm_hour == 0) {
if (format[offset] == 'I')
res = wait_file(chan, ints, "digits/pt-ah", lang);
if (!res)
res = wait_file(chan, ints, "digits/pt-meianoite", lang);
}
else if (tm.tm_hour == 12) {
if (format[offset] == 'I')
res = wait_file(chan, ints, "digits/pt-ao", lang);
if (!res)
res = wait_file(chan, ints, "digits/pt-meiodia", lang);
}
else {
if (format[offset] == 'I') {
res = wait_file(chan, ints, "digits/pt-ah", lang);
if ((tm.tm_hour % 12) != 1)
if (!res)
res = wait_file(chan, ints, "digits/pt-sss", lang);
}
if (!res)
res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
}
break;
case 'H':
case 'k':
/* 24-Hour */
res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
if (!res) {
if (tm.tm_hour != 0) {
int remainder = tm.tm_hour;
if (tm.tm_hour > 20) {
snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
res = wait_file(chan,ints,nextmsg,lang);
}
}
}
break;
case 'M':
/* Minute */
if (tm.tm_min == 0) {
res = wait_file(chan, ints, "digits/pt-hora", lang);
if (tm.tm_hour != 1)
if (!res)
res = wait_file(chan, ints, "digits/pt-sss", lang); } else {
res = wait_file(chan,ints,"digits/pt-e",lang);
if (!res)
res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
}
break;
case 'P':
case 'p':
/* AM/PM */
if (tm.tm_hour > 12)
res = wait_file(chan, ints, "digits/p-m", lang);
else if (tm.tm_hour && tm.tm_hour < 12)
res = wait_file(chan, ints, "digits/a-m", lang);
break;
case 'Q':
/* Shorthand for "Today", "Yesterday", or ABdY */
Tilghman Lesher
committed
/* XXX As emphasized elsewhere, this should the native way in your
* language to say the date, with changes in what you say, depending
* upon how recent the date is. XXX */
{
struct timeval now;
struct tm tmnow;
Kevin P. Fleming
committed
time_t beg_today, tt;
gettimeofday(&now,NULL);
Kevin P. Fleming
committed
tt = now.tv_sec;
ast_localtime(&tt,&tmnow,timezone);
/* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
/* In any case, it saves not having to do ast_mktime() */