Лучший способ синхронизировать клиентские часы JavaScript с датой сервера

Можно создать дерево наследования для контейнеров, отражающее дерево наследования данных. Если у вас есть следующие данные:

class Interface {
public:
    virtual ~Interface()
        {}
    virtual void print() = 0;
};

class Number : public Interface {
public:
    Number(int value) : x( value )
        {}
    int get() const
        { return x; }
    void print()
        { std::printf( "%d\n", get() ); };
private:
    int x;
};

class String : public Interface {
public:
    String(const std::string & value) : x( value )
        {}
    const std::string &get() const
        { return x; }
    void print()
        { std::printf( "%s\n", get().c_str() ); }
private:
    std::string x;
};

У вас также могут быть следующие контейнеры:

class GenericContainer {
public:
    GenericContainer()
        {}
    ~GenericContainer()
        { v.clear(); }

    virtual void add(Interface &obj)
        { v.push_back( &obj ); }
    Interface &get(unsigned int i)
        { return *v[ i ]; }
    unsigned int size() const
        { return v.size(); }
private:
    std::vector<Interface *> v;
};

class NumericContainer : public GenericContainer {
public:
    virtual void add(Number &obj)
        { GenericContainer::add( obj ); }
    Number &get(unsigned int i)
        { return (Number &) GenericContainer::get( i ); }
};

class TextContainer : public GenericContainer {
public:
    virtual void add(String &obj)
        { GenericContainer::add( obj ); }
    String &get(unsigned int i)
        { return (String &) GenericContainer::get( i ); }
};

Это не самый эффективный код; это просто, чтобы дать идею. Единственная проблема с этим подходом состоит в том, что каждый раз, когда вы добавляете новый класс данных, вы также должны создавать новый контейнер. Кроме того, у вас есть полиморфизм "снова работает". Вы можете быть конкретным или общим:

void print(GenericContainer & x)
{
    for(unsigned int i = 0; i < x.size(); ++i) {
        x.get( i ).print();
    }
}

void printNumbers(NumericContainer & x)
{
    for(unsigned int i = 0; i < x.size(); ++i) {
        printf( "Number: " );
        x.get( i ).print();
    }
}

int main()
{
    TextContainer strContainer;
    NumericContainer numContainer;
    Number n( 345 );
    String s( "Hello" );

    numContainer.add( n );
    strContainer.add( s );

    print( strContainer );
    print( numContainer );
    printNumbers( numContainer );
}
57
задан n0s 28 October 2009 в 16:44
поделиться

4 ответа

вы должны помнить время клиента между readyState == 2 и readyState == 3, если вы собираетесь использовать ajax, потому что время сервера будет установлено где-то между временем получения запроса и подготовленным ответом

9
ответ дан 24 November 2019 в 19:34
поделиться

Эти две функции Javascript должны помочь вам.

var offset = 0;
function calcOffset() {
    var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    xmlhttp.open("GET", "http://stackoverflow.com/", false);
    xmlhttp.send();

    var dateStr = xmlhttp.getResponseHeader('Date');
    var serverTimeMillisGMT = Date.parse(new Date(Date.parse(dateStr)).toUTCString());
    var localMillisUTC = Date.parse(new Date().toUTCString());

    offset = serverTimeMillisGMT -  localMillisUTC;
}

function getServerTime() {
    var date = new Date();

    date.setTime(date.getTime() + offset);

    return date;
}

РЕДАКТИРОВАТЬ: удалено ".replace (/ ^ (. ) [\ s \ S] /, "$ 1") ".

calcOffset () вычисляет смещение от времени сервера и компенсирует GMT / UTC.

getServerTime (), чтобы получить смещение местного времени для соответствия серверам, используя местный часовой пояс.

Если для выполнения calcOffset () требуется время, вы можете потерять точность на несколько секунд. Может быть, время выполнения может быть принято во внимание ....

Если вас беспокоит, что вычисленное смещение станет неверным, когда местное время или время сервера меняются на летнее или наоборот, вы можете пересчитывать немного после каждого часа. , система компенсирует изменения в летней экономии времени. Возможно, потребуется подождать, пока и локальные, и серверные часы не пройдут час.

Пример работает только в IE из-за "Msxml2.XMLHTTP", я думаю .....

38
ответ дан 24 November 2019 в 19:34
поделиться

Я бы запросил обновление с сервера каждые 30 секунд или около того, если вам нужна точность только до минуты. Ни в коем случае не полагайтесь на время клиента, а используйте его системные часы, чтобы часы оставались точными между обновлениями. Я думаю, вы сами ответили на свой вопрос?

Было бы полезно, если бы мы лучше понимали, что вы на самом деле пытаетесь сделать.

Если вы просто хотите, чтобы часы отображали время на сервере, которое затем настраивается на определенный часовой пояс, делать это на стороне клиента со смещениями. Обрабатывайте летнее время в часовых поясах, которые это применимо, используя дату, которую вы также получаете с сервера. Если вы хотите определить задержку, вам, вероятно, понадобится небольшой скрипт на сервере для расчета разницы. Но, как указано выше, это поможет лучше понять проблему. Если точность составляет только минуту, задержка кажется менее критичной.

0
ответ дан 24 November 2019 в 19:34
поделиться

Я бы синхронизировал время во время инициализации с помощью Internet Time Server.

http://tf.nist.gov/service/its.htm

-2
ответ дан 24 November 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: