*** utils.c.org Wed Jul 30 21:43:08 2003 --- utils.c Wed Jul 30 21:42:46 2003 *************** *** 473,475 **** --- 473,644 ---- convertStringToHexString ((char*)digest, id); pdf_printf("/ID [%s %s]\n", id, id); } + + /* Print the /CreationDate entry. + + PDF Reference, third edition says about the expected date format: +
+ 3.8.2 Dates + + PDF defines a standard date format, which closely follows that of + the international standard ASN.1 (Abstract Syntax Notation One), + defined in ISO/IEC 8824 (see the Bibliography). A date is a string + of the form + + (D:YYYYMMDDHHmmSSOHH'mm') + + where + + YYYY is the year + MM is the month + DD is the day (01-31) + HH is the hour (00-23) + mm is the minute (00-59) + SS is the second (00-59) + O is the relationship of local time to Universal Time (UT), + denoted by one of the characters +, -, or Z (see below) + HH followed by ' is the absolute value of the offset from UT + in hours (00-23) + mm followed by ' is the absolute value of the offset from UT + in minutes (00-59) + + The apostrophe character (') after HH and mm is part of the syntax. + All elds after the year are optional. (The prefix D:, although also + optional, is strongly recommended.) The default values for MM and DD + are both 01; all other numerical elds default to zero values. A plus + sign (+) as the value of the O field signifies that local time is + later than UT, a minus sign (-) that local time is earlier than UT, + and the letter Z that local time is equal to UT. If no UT information + is specified, the relationship of the specified time to UT is + considered to be unknown. Whether or not the time zone is known, the + rest of the date should be specified in local time. + + For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard + Time, is represented by the string + + D:199812231952-08'00' +
+ + The main difficulty is get the time zone data. Function strftime() + of glibc knows "%z", the manual page says: +
+ %z The time-zone as hour offset from GMT. Required to + emit RFC822-conformant dates (using "%a, %d %b %Y + %H:%M:%S %z"). (GNU) +
+ Does this mean that the output of "%z" can have any RFC822-conformant + format? + + RFC 822 specifies: +
+ 5. DATE AND TIME SPECIFICATION + + 5.1. SYNTAX + + [...] + + zone = "UT" / "GMT" ; Universal Time + ; North American : UT + / "EST" / "EDT" ; Eastern: - 5/ - 4 + / "CST" / "CDT" ; Central: - 6/ - 5 + / "MST" / "MDT" ; Mountain: - 7/ - 6 + / "PST" / "PDT" ; Pacific: - 8/ - 7 + / 1ALPHA ; Military: Z = UT; + ; A:-1; (J not used) + ; M:-12; N:+1; Y:+12 + / ( ("+" / "-") 4DIGIT ) ; Local differential + ; hours+min. (HHMM) +
+ */ + void printcreationdate() + { + time_t t; + struct tm *tt; + size_t size; + char time_str[40]; + char *zone_str; + + /* get the time */ + t = time(NULL); + tt = localtime(&t); + size = strftime(time_str, sizeof(time_str), "%Y%m%d%H%M%S%z", tt); + /* expected format: "YYYYmmddHHMMSSzzzzz" */ + + /* correction for seconds: %S can be in range 00..61, + the PDF reference expects 00..59, + therefore we map "60" and "61" to "59" */ + if (zone_str[12] == '6' && zone_str[13] != 0) { + zone_str[12] == '5'; + zone_str[13] == '9'; + } + + /* correction for time zone */ + zone_str = &time_str[14]; + if ((zone_str[0] == '+' || zone_str[0] == '-') && + isdigit(zone_str[1]) && + isdigit(zone_str[2]) && + isdigit(zone_str[3]) && + isdigit(zone_str[4]) && + zone_str[5] == 0) { + /* test for GMT */ + if (strcmp(&zone_str[1], "0000") == 0) { + /* case "+0000" or "-0000" */ + zone_str[0] = 'Z'; + zone_str[1] = 0; + } + else { + /* convert "sdddd" to "sdd'dd'" (s = sign, d = digit) */ + zone_str[7] = 0; + zone_str[6] = '\''; + zone_str[5] = zone_str[4]; + zone_str[4] = zone_str[3]; + zone_str[3] = '\''; + } + } + else if (strcmp(zone_str, "Z") == 0) { + /* case "Z", nothing to do */ + } + else if (strcmp(zone_str, "GMT") == 0 || + strcmp(zone_str, "UT") == 0) { + /* case Universal Time */ + zone_str[0] = 'Z'; + zone_str[1] = 0; + } + else if (zone_str[1] == 0 && + zone_str[0] >= 'A' && + zone_str[0] <= 'M') { + /* Military: A:-1 .. M:-12 */ + sprintf(zone_str, "-%02d'00'", zone_str[0] - 'A' + 1); + } + else if (zone_str[1] == 0 && + zone_str[0] >= 'N' && + zone_str[0] <= 'Y') { + /* Military: N:+1 .. Y:+12 */ + sprintf(zone_str, "+%02d'00'", zone_str[0] - 'N' + 1); + } + else if (strcmp(zone_str, "EDT") == 0) { + strcpy(zone_str, "-04'00'"); + } + else if (strcmp(zone_str, "EST") == 0 || + strcmp(zone_str, "CDT") == 0) { + strcpy(zone_str, "-05'00'"); + } + else if (strcmp(zone_str, "CST") == 0 || + strcmp(zone_str, "MDT") == 0) { + strcpy(zone_str, "-06'00'"); + } + else if (strcmp(zone_str, "MST") == 0 || + strcmp(zone_str, "PDT") == 0) { + strcpy(zone_str, "-07'00'"); + } + else if (strcmp(zone_str, "PST") == 0) { + strcpy(zone_str, "-08'00'"); + } + else { + /* unknown zone format or "%z" is not supported by strftime() */ + zone_str[0] = 0; + } + + /* print result */ + pdf_printf("/CreationDate (D:%s)\n", time_str); + }