VIT(R) SOFT(n)WARE(z) RELEASES(tm): all programs with sources: vit-time-lib.с.html

VIT(R) Time Functions Demo





// VitTimeLib.c
//
// Description on russian (charset KOI-8R).
//
// Убивши  немало времени, чтобы разобраться с функциями времени, не могу
// не поделиться впечатлениями.
// 
// В  C  библиотеке есть функции для преобразования time_t в tm (time_t -
// это  время в секундах с 1 янв 1970, а tm - структура, где: год, месяц,
// дни, часы, минуты, секунды).
// 
// Но  отсутствует  напрочь  функция  для  обратного  преобразования tm в
// time_t. А нужна (чтобы прочитать дату из http заголовков Last-Modified
// и  Date)!  Поиски  в  инете  кода  для  преобразования  tm в time_t не
// увенчались успехом, хотя потратил я на это несколько часов.
// 
// В  резульате  непредвиденно  больших  напрягов  родились таки функции,
// которые это делают - это хозяйство в аттаченном VitTimeLib.zip Там всё
// подогнано и проверено перебором всех дат (эта демка как раз перебирает
// и печатает различия).
// 
// И вот что интересно:
// 
// 1.  Программа,  компилировванная  Ms  Visual  C  6.0 возвращает NULL в
// результате вызова gmtime когда доходит до time_t t=0x80000000:
// time_t t=(time_t)0x80000000;
// struct tm *tmStruc = gmtime(&t);
// (это значит поддерживаются даты до 19.01.2038)
// 
// 2.  Программа,  компилированная GCC глючит (неправильную дату печатет,
// типа  1907  год),  когда  доходит  до time_t = 0x80000000. И под Linux
// тоже.
// 
// 3. Самый стойкий оловянный солдатик оказался WatcomC 11.0 - только при
// time_t t=0xF4D41F80 (01.03.2100) начинаются интересные вещи, наверное,
// там  действительно  произойдёт  сдвиг високосного года на нечётный или
// просто и у Watcom-а имеются глюки в библиотеке.
// 
// 4.  И  по-моему  (хотя  не  уверен), глючит под Linux-ом localtime() -
// выдаёт на 1 час меньше время.
// 
// 
//  24.08.2000
//  Vitaliy Vasiliev           mailto:vitaliy_vasiliev@mail.ru
//  http://www.chat.ru/~vitaliy_vasiliev/
//  http://free.prohosting.com/~vitivas/


#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#ifdef WIN32
 #include <io.h>
 #include <windows.h>
 #include <process.h>
#endif


void logoAndVersion(void) {
    printf("\n\
  VitTimeLib demo: VIT(R) Time Functions Demo\n\
  Version 1.0  Copyright (C) Vitaliy I. Vasiliev 24.08.2000\n\
  Vitaliy Vasiliev homepage: http://www.chat.ru/~vitaliy_vasiliev/\n\
  Vitaliy Vasiliev homepage mirror: http://free.prohosting.com/~vitivas/\n\
  \n\
");
}

void sleepThread(unsigned long dwMilliseconds) {
#ifdef _GNU_SOURCE
 #ifdef WIN32
    Sleep(dwMilliseconds); // under cygwin
 #else
    usleep(dwMilliseconds*1000); // under unix
 #endif
#else
    Sleep(dwMilliseconds); // under win
#endif
}

int szCmp(char *s1, char *s2) {
    #define CHAREOSTR ((unsigned char)'\0')
    #define StringCHAREOSTR "\0"
    if(*s1 == *s2) {
        while(*++s1 == *++s2) if((unsigned char)*s1<=CHAREOSTR) break;
    }
    return ((unsigned char)(*s1) - (unsigned char)(*s2));
}


time_t tmToTimeT(struct tm *tmStruc) {
    // Note: to convert tm --> time_t available library functions:
    //   tmStruc = gmtime(&timeOfDayGmt);
    //   tmStruc = localtime(&timeOfDayGmt);

    // struct  tm { // from <time.h>
    //     int tm_sec;   // seconds after the minute -- [0,61]
    //     int tm_min;   // minutes after the hour   -- [0,59]
    //     int tm_hour;  // hours after midnight     -- [0,23]
    //     int tm_mday;  // day of the month         -- [1,31]
    //     int tm_mon;   // months since January     -- [0,11]
    //     int tm_year;  // years since 1900
    //     int tm_wday;  // days since Sunday        -- [0,6]
    //     int tm_yday;  // days since January 1     -- [0,365]
    //     int tm_isdst; // Daylight Savings Time flag */
    // };

    unsigned long i, date, month, year;
    date  = tmStruc->tm_mday;      // now: date=1...31
    month = tmStruc->tm_mon;       // now: month=0...11
    year  = 1900+tmStruc->tm_year; // now: year=0...9999
    if(year<1970) return 0;
    year-=1970;
    i = year*366 + month*31 + (date-1);
    // subtracting number of full non-visokosnih years:
    i -= ((year+2)*3/4 - 1);
    // subtracting number of 30-day-months:
    if(month<7) i-=(month+0)/2;
    else        i-=(month-1)/2;
    // subtracting 28-day-feb (if after):
    if(((year+2)%4) == 0) { // if visokosniy year:
        if(month>1) i-=1;
    } else {                // if non-visokosniy year:
        if(month>1) i-=2;
    }
    i *= 24;
    i += tmStruc->tm_hour;
    i *= 60;
    i += tmStruc->tm_min;
    i *= 60;
    i += tmStruc->tm_sec;
    // WATCOM'S LIB after feb 2100: // // skip 1 day 01.03.2100 (in feb 2100)
    // WATCOM'S LIB after feb 2100: // if(i>=0xF4D57100) {
    // WATCOM'S LIB after feb 2100: //    i-=60*60*24; // 0x15180
    // WATCOM'S LIB after feb 2100: // }
    // WATCOM'S LIB after feb 2100: // if(i>=0xF72E9D00) {
    // WATCOM'S LIB after feb 2100: //    i+=60*60*24;
    // WATCOM'S LIB after feb 2100: // }
    return i;
}



time_t stringTimeToTimeT(char *timeStringBuf) {
    unsigned long i, date, month, year;
    date  = (*timeStringBuf++ - '0'); date*=10;
    date += (*timeStringBuf++ - '0');           // now: date=1...31
    timeStringBuf++; // skip '.'
    month  = (*timeStringBuf++ - '0'); month*=10;
    month += (*timeStringBuf++ - '0'); month--; // now: month=0...11
    timeStringBuf++; // skip '.'
    year  = (*timeStringBuf++ - '0'); year*=10;
    year += (*timeStringBuf++ - '0'); year*=10;
    year += (*timeStringBuf++ - '0'); year*=10;
    year += (*timeStringBuf++ - '0');           // now: year=0...9999
    if(year<1970) return 0;
    year-=1970;
    i = year*366 + month*31 + (date-1);
    // subtracting number of full non-visokosnih years:
    i -= ((year+2)*3/4 - 1);
    // subtracting number of 30-day-months:
    if(month<7) i-=(month+0)/2;
    else        i-=(month-1)/2;
    // subtracting 28-day-feb (if after):
    if(((year+2)%4) == 0) { // if visokosniy year:
        if(month>1) i-=1;
    } else {                // if non-visokosniy year:
        if(month>1) i-=2;
    }
    i *= 24;
    timeStringBuf++; // skip ' '
    i += (*timeStringBuf++ - '0')*10; // 0...2 (tens of hours)
    i += (*timeStringBuf++ - '0')   ; // 0...9 hours
    i *= 60;
    timeStringBuf++; // skip ':'
    i += (*timeStringBuf++ - '0')*10; // 0...5 (tens of minutes)
    i += (*timeStringBuf++ - '0')   ; // 0...9 minutes
    i *= 60;
    timeStringBuf++; // skip ':'
    i += (*timeStringBuf++ - '0')*10; // 0...5 (tens of seconds)
    i += (*timeStringBuf++ - '0')   ; // 0...9 seconds
    // WATCOM'S LIB after feb 2100: // // skip 1 day 01.03.2100 (in feb 2100)
    // WATCOM'S LIB after feb 2100: // if(i>=0xF4D57100) {
    // WATCOM'S LIB after feb 2100: //    i-=60*60*24; // 0x15180
    // WATCOM'S LIB after feb 2100: // }
    // WATCOM'S LIB after feb 2100: // if(i>=0xF72E9D00) {
    // WATCOM'S LIB after feb 2100: //    i+=60*60*24;
    // WATCOM'S LIB after feb 2100: // }
    return i;
}

void strftimeVit(char *timeStringBuf, time_t t) {
    // Note: time_t - is time in seconds since 1 jan 1970
    unsigned long tt;
    // WATCOM'S LIB after feb 2100: // // skip 1 day 01.03.2100 (in feb 2100 must be 28 days?):
    // WATCOM'S LIB after feb 2100: // if(t>=0xF4D41F80) t+=60*60*24;
    // init. buf:
    timeStringBuf+=19;
    *timeStringBuf-- = 0;
    *timeStringBuf-- = (char)('0'+((unsigned long)t%10)); t=(unsigned long)t/10; // seconds
    *timeStringBuf-- = (char)('0'+(t%6));  t/=6;  // tens of seconds
    *timeStringBuf-- = ':';
    *timeStringBuf-- = (char)('0'+(t%10)); t/=10; // minutes
    *timeStringBuf-- = (char)('0'+(t%6));  t/=6;  // tens of minutes
    *timeStringBuf-- = ':';
    *timeStringBuf-- = (char)('0'+((t%24)%10));      // hours
    *timeStringBuf-- = (char)('0'+(t%24)/10); t/=24; // tens of hours
    *timeStringBuf-- = ' ';
    // So, here t=days_from_1970_year:
    tt = 1968 + ((t+365+366)*4)/(365*4+1); // years:
    *timeStringBuf-- = (char)('0'+(tt%10));       // years '9'
    *timeStringBuf-- = (char)('0'+((tt/10)%10));  // years '9'
    *timeStringBuf-- = (char)('0'+((tt/100)%10)); // years '9'
    *timeStringBuf-- = (char)('0'+((tt/1000)%10));// years '1'
    // computation: days since 1 jan of nearest 4*year:
    t = t+365+366 - (unsigned long)((t+365+366)/(365*4+1)) * (365*4+1);
    if(t<366) { // visokosniy year
        t=t%366;
        if(t>=31+29) t++; // (december 29 days-->30 days)
    } else {
        t=(t-366)%365;
        if(t>=31+28) t++; // (december 29 days-->30 days)
        if(t>=31+28) t++;
    }
    if(t<=31+30+31+30+31+30+31) {
        tt = t%(31+30);     // day of 2*month (0...30)
        t  = t/(31+30);     // 2*month of year
        t  = t*2 + tt/31;   // month of year
        tt = tt%31;         // day of 2*month (0...30)
    } else {
        t--;
        tt = t%(31+30);     // day of 2*month (0...30)
        t  = t/(31+30);     // 2*month of year
        t  = t*2;
        if(tt>=30) {
            t++;            // month of year
            tt-=30;         // day of 2*month (0...30)
        }
    }
    tt++; // tt = day: 1...31
    t++;  // tt = month: 1...12
    *timeStringBuf-- = '.';
    *timeStringBuf-- = (char)('0'+(t%10)); // month of year
    *timeStringBuf-- = (char)('0'+(t/10)); // month of year
    *timeStringBuf-- = '.';
    *timeStringBuf-- = (char)('0'+(tt%10)); // day of month
    *timeStringBuf-- = (char)('0'+(tt/10)); // day of month
}

time_t getTzSecondsShift() {
    time_t timeOfDayGmt;
    time_t timeOfDayLocal;
    struct tm *tmStruc;
    timeOfDayGmt = 10000000; // time(NULL);
    tmStruc = localtime(&timeOfDayGmt);
    timeOfDayLocal = tmToTimeT(tmStruc);
    return timeOfDayLocal-timeOfDayGmt;
}

int main(int argc, char *argv[]) {
    time_t timeOfDayGmt;
    time_t timeOfDayLocal;
    char timeStringBuf[255];
    char genStringBuf[255];
    unsigned long i;
    int tzSecondsShift;

    logoAndVersion();

    tzSecondsShift = getTzSecondsShift();
    printf("TimeZone shift: getTzSecondsShift()=%d seconds (%d hours)\n", getTzSecondsShift(), tzSecondsShift/60/60);

    timeOfDayGmt = time(NULL);
    strftimeVit(timeStringBuf, timeOfDayGmt);
    printf("time(NULL)               =%d: Now time GMT  : %s\n", timeOfDayGmt, timeStringBuf);

    timeOfDayLocal = timeOfDayGmt+tzSecondsShift;
    strftimeVit(timeStringBuf, timeOfDayLocal);
    printf("time(NULL)+tzSecondsShift=%d: Now time LOCAL: %s\n", timeOfDayLocal, timeStringBuf);

    for(i=0; ; ) {
        struct tm *tmStruc;
        time_t t;
        //timeOfDayGmt = time(NULL);
        timeOfDayGmt=i;
        tmStruc = gmtime(&timeOfDayGmt);
        //tmStruc = localtime(&timeOfDayGmt);
        sprintf(timeStringBuf, "%02d.%02d.%04d %02d:%02d:%02d", tmStruc->tm_mday, tmStruc->tm_mon+1, 1900+tmStruc->tm_year, tmStruc->tm_hour, tmStruc->tm_min, tmStruc->tm_sec);
        strftimeVit(genStringBuf, i);
        t = stringTimeToTimeT(genStringBuf);
        if((int)t!=(int)i || szCmp(timeStringBuf, genStringBuf)!=0) {
            printf("i=0x%X t=0x%X tm_yday=%d %s|%s|\n", i, t, tmStruc->tm_yday, timeStringBuf, genStringBuf);
            sleepThread(2000);
        }
        //if(++i == 0) break;
        if((i+=60*60*24) > 0xfff00000) break;
    }
    exit(0);
    return 0;
}








back to products.html

Сайт управляется системой uCoz


Created: august 24, 2000,
http://www.chat.ru/~vitaliy_vasiliev/   http://free.prohosting.com/~vitivas/

<noscript></html>