forked from Mirrorlandia_minetest/minetest
Clean up getTime helpers
This increases size of the getTime return values to 64 bits. It also removes the TimeGetter classes since the getTime functions are now very precise.
This commit is contained in:
parent
7f4cdbcbe9
commit
b662a4577d
@ -1618,7 +1618,7 @@ float Client::mediaReceiveProgress()
|
||||
typedef struct TextureUpdateArgs {
|
||||
IrrlichtDevice *device;
|
||||
gui::IGUIEnvironment *guienv;
|
||||
u32 last_time_ms;
|
||||
u64 last_time_ms;
|
||||
u16 last_percent;
|
||||
const wchar_t* text_base;
|
||||
ITextureSource *tsrc;
|
||||
@ -1634,7 +1634,7 @@ void texture_update_progress(void *args, u32 progress, u32 max_progress)
|
||||
u32 time_ms = targs->last_time_ms;
|
||||
if (cur_percent != targs->last_percent) {
|
||||
targs->last_percent = cur_percent;
|
||||
time_ms = getTimeMs();
|
||||
time_ms = porting::getTimeMs();
|
||||
// only draw when the user will notice something:
|
||||
do_draw = (time_ms - targs->last_time_ms > 100);
|
||||
}
|
||||
@ -1692,7 +1692,7 @@ void Client::afterContentReceived(IrrlichtDevice *device)
|
||||
TextureUpdateArgs tu_args;
|
||||
tu_args.device = device;
|
||||
tu_args.guienv = guienv;
|
||||
tu_args.last_time_ms = getTimeMs();
|
||||
tu_args.last_time_ms = porting::getTimeMs();
|
||||
tu_args.last_percent = 0;
|
||||
tu_args.text_base = wgettext("Initializing nodes");
|
||||
tu_args.tsrc = m_tsrc;
|
||||
|
@ -51,22 +51,6 @@ bool noMenuActive()
|
||||
MainGameCallback *g_gamecallback = NULL;
|
||||
|
||||
|
||||
// Instance of the time getter
|
||||
static TimeGetter *g_timegetter = NULL;
|
||||
|
||||
u32 getTimeMs()
|
||||
{
|
||||
if (g_timegetter == NULL)
|
||||
return 0;
|
||||
return g_timegetter->getTime(PRECISION_MILLI);
|
||||
}
|
||||
|
||||
u32 getTime(TimePrecision prec) {
|
||||
if (g_timegetter == NULL)
|
||||
return 0;
|
||||
return g_timegetter->getTime(prec);
|
||||
}
|
||||
|
||||
ClientLauncher::~ClientLauncher()
|
||||
{
|
||||
if (receiver)
|
||||
@ -96,9 +80,6 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create time getter
|
||||
g_timegetter = new IrrlichtTimeGetter(device);
|
||||
|
||||
// Speed tests (done after irrlicht is loaded to get timer)
|
||||
if (cmd_args.getFlag("speedtests")) {
|
||||
dstream << "Running speed tests" << std::endl;
|
||||
|
@ -24,42 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client/inputhandler.h"
|
||||
#include "gameparams.h"
|
||||
|
||||
// A small helper class
|
||||
class TimeGetter
|
||||
{
|
||||
public:
|
||||
virtual u32 getTime(TimePrecision prec) = 0;
|
||||
};
|
||||
|
||||
// A precise irrlicht one
|
||||
class IrrlichtTimeGetter: public TimeGetter
|
||||
{
|
||||
public:
|
||||
IrrlichtTimeGetter(IrrlichtDevice *device):
|
||||
m_device(device)
|
||||
{}
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
if (prec == PRECISION_MILLI) {
|
||||
if (m_device == NULL)
|
||||
return 0;
|
||||
return m_device->getTimer()->getRealTime();
|
||||
} else {
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
}
|
||||
private:
|
||||
IrrlichtDevice *m_device;
|
||||
};
|
||||
// Not so precise one which works without irrlicht
|
||||
class SimpleTimeGetter: public TimeGetter
|
||||
{
|
||||
public:
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
};
|
||||
|
||||
class ClientLauncher
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "keys.h"
|
||||
#include "settings.h"
|
||||
#include "gettime.h"
|
||||
#include "porting.h"
|
||||
#include "../util/string.h"
|
||||
|
||||
bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
|
||||
@ -199,7 +200,7 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
|
||||
if (ev.Joystick != m_joystick_id)
|
||||
return false;
|
||||
|
||||
m_internal_time = getTimeMs() / 1000.f;
|
||||
m_internal_time = porting::getTimeMs() / 1000.f;
|
||||
|
||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;
|
||||
|
||||
|
@ -592,7 +592,7 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||
|
||||
u32 RemoteClient::uptime()
|
||||
{
|
||||
return getTime(PRECISION_SECONDS) - m_connection_time;
|
||||
return porting::getTime(PRECISION_SECONDS) - m_connection_time;
|
||||
}
|
||||
|
||||
ClientInterface::ClientInterface(con::Connection* con)
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "threading/mutex.h"
|
||||
#include "network/networkpacket.h"
|
||||
#include "util/cpp11_container.h"
|
||||
#include "porting.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
@ -265,7 +266,7 @@ public:
|
||||
m_version_patch(0),
|
||||
m_full_version("unknown"),
|
||||
m_deployed_compression(0),
|
||||
m_connection_time(getTime(PRECISION_SECONDS))
|
||||
m_connection_time(porting::getTime(PRECISION_SECONDS))
|
||||
{
|
||||
}
|
||||
~RemoteClient()
|
||||
|
@ -71,7 +71,7 @@ int Database_SQLite3::busyHandler(void *data, int count)
|
||||
{
|
||||
s64 &first_time = reinterpret_cast<s64 *>(data)[0];
|
||||
s64 &prev_time = reinterpret_cast<s64 *>(data)[1];
|
||||
s64 cur_time = getTimeMs();
|
||||
s64 cur_time = porting::getTimeMs();
|
||||
|
||||
if (count == 0) {
|
||||
first_time = cur_time;
|
||||
|
@ -21,33 +21,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define GETTIME_HEADER
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
Get a millisecond counter value.
|
||||
Precision depends on implementation.
|
||||
Overflows at any value above 10000000.
|
||||
|
||||
Implementation of this is done in:
|
||||
Normal build: main.cpp
|
||||
Server build: servermain.cpp
|
||||
*/
|
||||
enum TimePrecision
|
||||
{
|
||||
PRECISION_SECONDS = 0,
|
||||
PRECISION_SECONDS,
|
||||
PRECISION_MILLI,
|
||||
PRECISION_MICRO,
|
||||
PRECISION_NANO
|
||||
};
|
||||
|
||||
extern u32 getTimeMs();
|
||||
extern u32 getTime(TimePrecision prec);
|
||||
|
||||
/*
|
||||
Timestamp stuff
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
inline std::string getTimestamp()
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ GUIChatConsole::GUIChatConsole(
|
||||
m_client(client),
|
||||
m_menumgr(menumgr),
|
||||
m_screensize(v2u32(0,0)),
|
||||
m_animate_time_old(0),
|
||||
m_animate_time_old(porting::getTimeMs()),
|
||||
m_open(false),
|
||||
m_close_on_enter(false),
|
||||
m_height(0),
|
||||
@ -71,8 +71,6 @@ GUIChatConsole::GUIChatConsole(
|
||||
m_font(NULL),
|
||||
m_fontsize(0, 0)
|
||||
{
|
||||
m_animate_time_old = getTimeMs();
|
||||
|
||||
// load background settings
|
||||
s32 console_alpha = g_settings->getS32("console_alpha");
|
||||
m_background_color.setAlpha(clamp_u8(console_alpha));
|
||||
@ -124,7 +122,7 @@ void GUIChatConsole::openConsole(f32 scale)
|
||||
m_desired_height_fraction = scale;
|
||||
m_desired_height = scale * m_screensize.Y;
|
||||
reformatConsole();
|
||||
m_animate_time_old = getTimeMs();
|
||||
m_animate_time_old = porting::getTimeMs();
|
||||
IGUIElement::setVisible(true);
|
||||
Environment->setFocus(this);
|
||||
m_menumgr->createdMenu(this);
|
||||
@ -212,7 +210,7 @@ void GUIChatConsole::draw()
|
||||
}
|
||||
|
||||
// Animation
|
||||
u32 now = getTimeMs();
|
||||
u64 now = porting::getTimeMs();
|
||||
animate(now - m_animate_time_old);
|
||||
m_animate_time_old = now;
|
||||
|
||||
|
@ -98,7 +98,7 @@ private:
|
||||
v2u32 m_screensize;
|
||||
|
||||
// used to compute how much time passed since last animate()
|
||||
u32 m_animate_time_old;
|
||||
u64 m_animate_time_old;
|
||||
|
||||
// should the console be opened or closed?
|
||||
bool m_open;
|
||||
|
@ -2664,9 +2664,9 @@ void GUIFormSpecMenu::drawMenu()
|
||||
m_old_tooltip = L"";
|
||||
} else {
|
||||
if (id == m_old_tooltip_id) {
|
||||
delta = porting::getDeltaMs(m_hovered_time, getTimeMs());
|
||||
delta = porting::getDeltaMs(m_hovered_time, porting::getTimeMs());
|
||||
} else {
|
||||
m_hovered_time = getTimeMs();
|
||||
m_hovered_time = porting::getTimeMs();
|
||||
m_old_tooltip_id = id;
|
||||
}
|
||||
}
|
||||
@ -3244,10 +3244,10 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
|
||||
m_doubleclickdetect[0].time = m_doubleclickdetect[1].time;
|
||||
|
||||
m_doubleclickdetect[1].pos = m_pointer;
|
||||
m_doubleclickdetect[1].time = getTimeMs();
|
||||
m_doubleclickdetect[1].time = porting::getTimeMs();
|
||||
}
|
||||
else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
|
||||
u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, getTimeMs());
|
||||
u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, porting::getTimeMs());
|
||||
if (delta > 400) {
|
||||
return false;
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ protected:
|
||||
gui::IGUIStaticText *m_tooltip_element;
|
||||
|
||||
u32 m_tooltip_show_delay;
|
||||
s32 m_hovered_time;
|
||||
s64 m_hovered_time;
|
||||
s32 m_old_tooltip_id;
|
||||
std::wstring m_old_tooltip;
|
||||
|
||||
@ -527,7 +527,7 @@ private:
|
||||
struct clickpos
|
||||
{
|
||||
v2s32 pos;
|
||||
s32 time;
|
||||
s64 time;
|
||||
};
|
||||
clickpos m_doubleclickdetect[2];
|
||||
|
||||
|
@ -828,7 +828,7 @@ bool GUITable::OnEvent(const SEvent &event)
|
||||
}
|
||||
else if (event.KeyInput.PressedDown && event.KeyInput.Char) {
|
||||
// change selection based on text as it is typed
|
||||
s32 now = getTimeMs();
|
||||
u64 now = porting::getTimeMs();
|
||||
if (now - m_keynav_time >= 500)
|
||||
m_keynav_buffer = L"";
|
||||
m_keynav_time = now;
|
||||
|
@ -196,7 +196,7 @@ protected:
|
||||
bool m_sel_doubleclick;
|
||||
|
||||
// Keyboard navigation stuff
|
||||
s32 m_keynav_time;
|
||||
u64 m_keynav_time;
|
||||
core::stringw m_keynav_buffer;
|
||||
|
||||
// Drawing and geometry information
|
||||
|
@ -619,7 +619,7 @@ void Hud::resizeHotbar() {
|
||||
}
|
||||
|
||||
struct MeshTimeInfo {
|
||||
s32 time;
|
||||
s64 time;
|
||||
scene::IMesh *mesh;
|
||||
};
|
||||
|
||||
@ -653,9 +653,9 @@ void drawItemStack(video::IVideoDriver *driver,
|
||||
MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
|
||||
if (mesh != ti.mesh) {
|
||||
ti.mesh = mesh;
|
||||
ti.time = getTimeMs();
|
||||
ti.time = porting::getTimeMs();
|
||||
} else {
|
||||
delta = porting::getDeltaMs(ti.time, getTimeMs()) % 100000;
|
||||
delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
|
||||
}
|
||||
}
|
||||
core::rect<s32> oldViewPort = driver->getViewPort();
|
||||
|
18
src/main.cpp
18
src/main.cpp
@ -107,24 +107,6 @@ static bool migrate_map_database(const GameParams &game_params, const Settings &
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
gettime.h implementation
|
||||
*/
|
||||
|
||||
#ifdef SERVER
|
||||
|
||||
u32 getTimeMs()
|
||||
{
|
||||
/* Use imprecise system calls directly (from porting.h) */
|
||||
return porting::getTime(PRECISION_MILLI);
|
||||
}
|
||||
|
||||
u32 getTime(TimePrecision prec)
|
||||
{
|
||||
return porting::getTime(prec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FileLogOutput file_log_output;
|
||||
|
||||
|
@ -981,7 +981,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
|
||||
|
||||
time_until_purge *= 1000; // seconds -> milliseconds
|
||||
|
||||
u32 curr_time = getTime(PRECISION_MILLI);
|
||||
u32 curr_time = porting::getTime(PRECISION_MILLI);
|
||||
u32 prev_unprocessed = m_unprocessed_count;
|
||||
m_unprocessed_count = m_transforming_liquid.size();
|
||||
|
||||
|
@ -942,5 +942,18 @@ void attachOrCreateConsole(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load performance counter frequency only once at startup
|
||||
#ifdef _WIN32
|
||||
|
||||
inline double get_perf_freq()
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return freq.QuadPart;
|
||||
}
|
||||
|
||||
double perf_freq = get_perf_freq();
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace porting
|
||||
|
@ -181,44 +181,32 @@ std::string get_sysinfo();
|
||||
|
||||
void initIrrlicht(irr::IrrlichtDevice * );
|
||||
|
||||
/*
|
||||
Resolution is 10-20ms.
|
||||
Remember to check for overflows.
|
||||
Overflow can occur at any value higher than 10000000.
|
||||
*/
|
||||
|
||||
// Monotonic counter getters.
|
||||
|
||||
#ifdef _WIN32 // Windows
|
||||
|
||||
inline u32 getTimeS()
|
||||
{
|
||||
return GetTickCount() / 1000;
|
||||
}
|
||||
extern double perf_freq;
|
||||
|
||||
inline u32 getTimeMs()
|
||||
inline u64 os_get_time(double mult)
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
inline u32 getTimeUs()
|
||||
{
|
||||
LARGE_INTEGER freq, t;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
LARGE_INTEGER t;
|
||||
QueryPerformanceCounter(&t);
|
||||
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0);
|
||||
return static_cast<double>(t.QuadPart) / (perf_freq / mult);
|
||||
}
|
||||
|
||||
inline u32 getTimeNs()
|
||||
{
|
||||
LARGE_INTEGER freq, t;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&t);
|
||||
return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0);
|
||||
}
|
||||
// Resolution is <1us.
|
||||
inline u64 getTimeS() { return os_get_time(1); }
|
||||
inline u64 getTimeMs() { return os_get_time(1000); }
|
||||
inline u64 getTimeUs() { return os_get_time(1000*1000); }
|
||||
inline u64 getTimeNs() { return os_get_time(1000*1000*1000); }
|
||||
|
||||
#else // Posix
|
||||
inline void _os_get_clock(struct timespec *ts)
|
||||
|
||||
inline void os_get_clock(struct timespec *ts)
|
||||
{
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
// from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
|
||||
// From http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
|
||||
// OS X does not have clock_gettime, use clock_get_time
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
@ -235,70 +223,57 @@ void initIrrlicht(irr::IrrlichtDevice * );
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ts);
|
||||
#endif // defined(__MACH__) && defined(__APPLE__)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Note: these clock functions do not return wall time, but
|
||||
// generally a clock that starts at 0 when the process starts.
|
||||
inline u32 getTimeS()
|
||||
inline u64 getTimeS()
|
||||
{
|
||||
struct timespec ts;
|
||||
_os_get_clock(&ts);
|
||||
os_get_clock(&ts);
|
||||
return ts.tv_sec;
|
||||
}
|
||||
|
||||
inline u32 getTimeMs()
|
||||
inline u64 getTimeMs()
|
||||
{
|
||||
struct timespec ts;
|
||||
_os_get_clock(&ts);
|
||||
os_get_clock(&ts);
|
||||
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
inline u32 getTimeUs()
|
||||
inline u64 getTimeUs()
|
||||
{
|
||||
struct timespec ts;
|
||||
_os_get_clock(&ts);
|
||||
os_get_clock(&ts);
|
||||
return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
inline u32 getTimeNs()
|
||||
inline u64 getTimeNs()
|
||||
{
|
||||
struct timespec ts;
|
||||
_os_get_clock(&ts);
|
||||
os_get_clock(&ts);
|
||||
return ts.tv_sec * 1000000000 + ts.tv_nsec;
|
||||
}
|
||||
|
||||
/*#include <sys/timeb.h>
|
||||
inline u32 getTimeMs()
|
||||
{
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
return tb.time * 1000 + tb.millitm;
|
||||
}*/
|
||||
#endif
|
||||
|
||||
inline u32 getTime(TimePrecision prec)
|
||||
inline u64 getTime(TimePrecision prec)
|
||||
{
|
||||
switch (prec) {
|
||||
case PRECISION_SECONDS:
|
||||
return getTimeS();
|
||||
case PRECISION_MILLI:
|
||||
return getTimeMs();
|
||||
case PRECISION_MICRO:
|
||||
return getTimeUs();
|
||||
case PRECISION_NANO:
|
||||
return getTimeNs();
|
||||
case PRECISION_SECONDS: return getTimeS();
|
||||
case PRECISION_MILLI: return getTimeMs();
|
||||
case PRECISION_MICRO: return getTimeUs();
|
||||
case PRECISION_NANO: return getTimeNs();
|
||||
}
|
||||
return 0;
|
||||
FATAL_ERROR("Called getTime with invalid time precision");
|
||||
}
|
||||
|
||||
/**
|
||||
* Delta calculation function taking two 32bit arguments.
|
||||
* @param old_time_ms old time for delta calculation (order is relevant!)
|
||||
* @param new_time_ms new time for delta calculation (order is relevant!)
|
||||
* @return positive 32bit delta value
|
||||
* Delta calculation function arguments.
|
||||
* @param old_time_ms old time for delta calculation
|
||||
* @param new_time_ms new time for delta calculation
|
||||
* @return positive delta value
|
||||
*/
|
||||
inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms)
|
||||
inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms)
|
||||
{
|
||||
if (new_time_ms >= old_time_ms) {
|
||||
return (new_time_ms - old_time_ms);
|
||||
|
@ -794,7 +794,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
if (m_move_id == -1) {
|
||||
m_move_id = event.TouchInput.ID;
|
||||
m_move_has_really_moved = false;
|
||||
m_move_downtime = getTimeMs();
|
||||
m_move_downtime = porting::getTimeMs();
|
||||
m_move_downlocation = v2s32(event.TouchInput.X, event.TouchInput.Y);
|
||||
m_move_sent_as_mouse_event = false;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ private:
|
||||
|
||||
int m_move_id;
|
||||
bool m_move_has_really_moved;
|
||||
s32 m_move_downtime;
|
||||
s64 m_move_downtime;
|
||||
bool m_move_sent_as_mouse_event;
|
||||
v2s32 m_move_downlocation;
|
||||
|
||||
|
@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "timetaker.h"
|
||||
|
||||
#include "../gettime.h"
|
||||
#include "../porting.h"
|
||||
#include "../log.h"
|
||||
#include <ostream>
|
||||
|
||||
@ -29,14 +29,14 @@ TimeTaker::TimeTaker(const char *name, u32 *result, TimePrecision prec)
|
||||
m_result = result;
|
||||
m_running = true;
|
||||
m_precision = prec;
|
||||
m_time1 = getTime(prec);
|
||||
m_time1 = porting::getTime(prec);
|
||||
}
|
||||
|
||||
u32 TimeTaker::stop(bool quiet)
|
||||
{
|
||||
if(m_running)
|
||||
{
|
||||
u32 time2 = getTime(m_precision);
|
||||
u32 time2 = porting::getTime(m_precision);
|
||||
u32 dtime = time2 - m_time1;
|
||||
if(m_result != NULL)
|
||||
{
|
||||
@ -64,7 +64,7 @@ u32 TimeTaker::stop(bool quiet)
|
||||
|
||||
u32 TimeTaker::getTimerTime()
|
||||
{
|
||||
u32 time2 = getTime(m_precision);
|
||||
u32 time2 = porting::getTime(m_precision);
|
||||
u32 dtime = time2 - m_time1;
|
||||
return dtime;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user