diff --git a/binaries/data/mods/public/gui/common/functions_utility.js b/binaries/data/mods/public/gui/common/functions_utility.js index 59dfcc6a0e..4c04fc939f 100644 --- a/binaries/data/mods/public/gui/common/functions_utility.js +++ b/binaries/data/mods/public/gui/common/functions_utility.js @@ -132,7 +132,7 @@ function timeToString(time) var format = translate("mm:ss"); else var format = translate("HH:mm:ss"); - return Engine.FormatMillisecondsIntoDateString(time, format); + return Engine.FormatMillisecondsIntoDateStringGMT(time, format); } function removeDupes(array) diff --git a/binaries/data/mods/public/gui/common/functions_utility_loadsave.js b/binaries/data/mods/public/gui/common/functions_utility_loadsave.js index c6254ca5a2..e6d021b145 100644 --- a/binaries/data/mods/public/gui/common/functions_utility_loadsave.js +++ b/binaries/data/mods/public/gui/common/functions_utility_loadsave.js @@ -5,7 +5,7 @@ function sortDecreasingDate(a, b) function generateLabel(metadata, engineInfo) { - let dateTimeString = Engine.FormatMillisecondsIntoDateString(metadata.time*1000, translate("yyyy-MM-dd HH:mm:ss")); + let dateTimeString = Engine.FormatMillisecondsIntoDateStringLocal(metadata.time*1000, translate("yyyy-MM-dd HH:mm:ss")); let dateString = sprintf(translate("\\[%(date)s]"), { "date": dateTimeString }); if (engineInfo) diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index f935ef8f7c..439fd5a6cb 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -1823,7 +1823,7 @@ function addChatMessage(msg) if (Engine.ConfigDB_GetValue("user", "chat.timestamp") == "true") text = sprintf(translate("%(time)s %(message)s"), { "time": sprintf(translate("\\[%(time)s]"), { - "time": Engine.FormatMillisecondsIntoDateString(new Date().getTime(), translate("HH:mm")) + "time": Engine.FormatMillisecondsIntoDateStringLocal(new Date().getTime(), translate("HH:mm")) }), "message": text }); diff --git a/binaries/data/mods/public/gui/lobby/lobby.js b/binaries/data/mods/public/gui/lobby/lobby.js index 9b4989c5f7..37ead8cc8d 100644 --- a/binaries/data/mods/public/gui/lobby/lobby.js +++ b/binaries/data/mods/public/gui/lobby/lobby.js @@ -632,7 +632,7 @@ function updateGameSelection() sgGameStartTime.caption = sprintf( // Translation: %(time)s is the hour and minute here. translate("Game started at %(time)s"), { - "time": Engine.FormatMillisecondsIntoDateString(+game.startTime*1000, translate("HH:mm")) + "time": Engine.FormatMillisecondsIntoDateStringLocal(+game.startTime*1000, translate("HH:mm")) }); sgNbPlayers.caption = sprintf( @@ -993,7 +993,7 @@ function ircFormat(msg) // Translation: Time as shown in the multiplayer lobby (when you enable it in the options page). // For a list of symbols that you can use, see: // https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table - let timeString = Engine.FormatMillisecondsIntoDateString(time.getTime(), translate("HH:mm")); + let timeString = Engine.FormatMillisecondsIntoDateStringLocal(time.getTime(), translate("HH:mm")); // Translation: Time prefix as shown in the multiplayer lobby (when you enable it in the options page). let timePrefixString = sprintf(translate("\\[%(time)s]"), { diff --git a/binaries/data/mods/public/gui/replaymenu/replay_menu.js b/binaries/data/mods/public/gui/replaymenu/replay_menu.js index 5a46e33c04..c4db73d415 100644 --- a/binaries/data/mods/public/gui/replaymenu/replay_menu.js +++ b/binaries/data/mods/public/gui/replaymenu/replay_menu.js @@ -300,7 +300,7 @@ function greyout(text, isCompatible) */ function getReplayDateTime(replay) { - return Engine.FormatMillisecondsIntoDateString(replay.timestamp * 1000, translate("yyyy-MM-dd HH:mm")); + return Engine.FormatMillisecondsIntoDateStringLocal(replay.timestamp * 1000, translate("yyyy-MM-dd HH:mm")); } /** @@ -330,7 +330,7 @@ function getReplayMapName(replay) */ function getReplayMonth(replay) { - return Engine.FormatMillisecondsIntoDateString(replay.timestamp * 1000, translate("yyyy-MM")); + return Engine.FormatMillisecondsIntoDateStringLocal(replay.timestamp * 1000, translate("yyyy-MM")); } /** diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js index bba01a3294..28fd17b14a 100644 --- a/binaries/data/mods/public/gui/session/messages.js +++ b/binaries/data/mods/public/gui/session/messages.js @@ -787,7 +787,7 @@ function addChatMessage(msg) let historical = { "txt": formatted, "timePrefix": sprintf(translate("\\[%(time)s]"), { - "time": Engine.FormatMillisecondsIntoDateString(new Date().getTime(), translate("HH:mm")) + "time": Engine.FormatMillisecondsIntoDateStringLocal(new Date().getTime(), translate("HH:mm")) }), "filter": {} }; diff --git a/source/i18n/L10n.cpp b/source/i18n/L10n.cpp index c371fbfb75..d9e5da4bdc 100644 --- a/source/i18n/L10n.cpp +++ b/source/i18n/L10n.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 Wildfire Games +/* Copyright (c) 2017 Wildfire Games * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -360,7 +360,7 @@ UDate L10n::ParseDateTime(const std::string& dateTimeString, const std::string& return date; } -std::string L10n::LocalizeDateTime(const UDate& dateTime, const DateTimeType& type, const DateFormat::EStyle& style) const +std::string L10n::LocalizeDateTime(const UDate dateTime, const DateTimeType& type, const DateFormat::EStyle& style) const { UnicodeString utf16Date; @@ -375,7 +375,7 @@ std::string L10n::LocalizeDateTime(const UDate& dateTime, const DateTimeType& ty return std::string(utf8Date, sink.NumberOfBytesWritten()); } -std::string L10n::FormatMillisecondsIntoDateString(const UDate& milliseconds, const std::string& formatString) const +std::string L10n::FormatMillisecondsIntoDateString(const UDate milliseconds, const std::string& formatString, bool useLocalTimezone) const { UErrorCode status = U_ZERO_ERROR; UnicodeString dateString; @@ -386,7 +386,7 @@ std::string L10n::FormatMillisecondsIntoDateString(const UDate& milliseconds, co if (U_FAILURE(status)) LOGERROR("Error creating SimpleDateFormat: %s", u_errorName(status)); - const TimeZone* timeZone = TimeZone::createDefault(); + const TimeZone* timeZone = useLocalTimezone ? TimeZone::createDefault() : TimeZone::getGMT() ; status = U_ZERO_ERROR; Calendar* calendar = Calendar::createInstance(*timeZone, currentLocale, status); diff --git a/source/i18n/L10n.h b/source/i18n/L10n.h index be09477d12..fdc6de5d43 100644 --- a/source/i18n/L10n.h +++ b/source/i18n/L10n.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 Wildfire Games +/* Copyright (c) 2017 Wildfire Games * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -424,10 +424,10 @@ public: * @sa http://en.wikipedia.org/wiki/Unix_time * @sa http://icu-project.org/apiref/icu4c521/classicu_1_1DateFormat.html */ - std::string LocalizeDateTime(const UDate& dateTime, const DateTimeType& type, const DateFormat::EStyle& style) const; + std::string LocalizeDateTime(const UDate dateTime, const DateTimeType& type, const DateFormat::EStyle& style) const; /** - * Returns the specified date converted to the local timezone using the specified date format. + * Returns the specified date using the specified date format. * * @param milliseconds Date specified as a UNIX timestamp in milliseconds * (not seconds). @@ -435,13 +435,14 @@ public: * symbols. Usually, you internationalize the format string and * get it translated before you pass it to * FormatMillisecondsIntoDateString(). + * @param useLocalTimezone Boolean useful for durations * @return String containing the specified date with the specified date * format. * * @sa http://en.wikipedia.org/wiki/Unix_time * @sa https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table */ - std::string FormatMillisecondsIntoDateString(const UDate& milliseconds, const std::string& formatString) const; + std::string FormatMillisecondsIntoDateString(const UDate milliseconds, const std::string& formatString, bool useLocalTimezone) const; /** * Returns the specified floating-point number as a string, with the number diff --git a/source/i18n/scripting/JSInterface_L10n.cpp b/source/i18n/scripting/JSInterface_L10n.cpp index e31c02c506..6368f5a7a7 100644 --- a/source/i18n/scripting/JSInterface_L10n.cpp +++ b/source/i18n/scripting/JSInterface_L10n.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -69,9 +69,15 @@ std::wstring JSI_L10n::GetFallbackToAvailableDictLocale(ScriptInterface::CxPriva } // Return a localized version of a time given in milliseconds. -std::wstring JSI_L10n::FormatMillisecondsIntoDateString(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString) +std::wstring JSI_L10n::FormatMillisecondsIntoDateStringLocal(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString) { - return wstring_from_utf8(g_L10n.FormatMillisecondsIntoDateString(milliseconds, utf8_from_wstring(formatString))); + return wstring_from_utf8(g_L10n.FormatMillisecondsIntoDateString(milliseconds, utf8_from_wstring(formatString), true)); +} + +// Return a localized version of a duration or a time in GMT given in milliseconds. +std::wstring JSI_L10n::FormatMillisecondsIntoDateStringGMT(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString) +{ + return wstring_from_utf8(g_L10n.FormatMillisecondsIntoDateString(milliseconds, utf8_from_wstring(formatString), false)); } // Return a localized version of the given decimal number. @@ -159,7 +165,8 @@ void JSI_L10n::RegisterScriptFunctions(ScriptInterface& scriptInterface) scriptInterface.RegisterFunction("TranslatePluralWithContext"); scriptInterface.RegisterFunction("TranslateLines"); scriptInterface.RegisterFunction, std::vector, &TranslateArray>("TranslateArray"); - scriptInterface.RegisterFunction("FormatMillisecondsIntoDateString"); + scriptInterface.RegisterFunction("FormatMillisecondsIntoDateStringLocal"); + scriptInterface.RegisterFunction("FormatMillisecondsIntoDateStringGMT"); scriptInterface.RegisterFunction("FormatDecimalNumberIntoString"); scriptInterface.RegisterFunction, &GetSupportedLocaleBaseNames>("GetSupportedLocaleBaseNames"); diff --git a/source/i18n/scripting/JSInterface_L10n.h b/source/i18n/scripting/JSInterface_L10n.h index e2c28d4b01..b7f050a947 100644 --- a/source/i18n/scripting/JSInterface_L10n.h +++ b/source/i18n/scripting/JSInterface_L10n.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -172,7 +172,29 @@ namespace JSI_L10n * @sa http://en.wikipedia.org/wiki/Unix_time * @sa https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table */ - std::wstring FormatMillisecondsIntoDateString(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString); + std::wstring FormatMillisecondsIntoDateStringLocal(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString); + + /** + * Returns the specified date in GMT using the specified date format. + * + * This is a JavaScript interface to + * L10n::FormatMillisecondsIntoDateString(). + * + * @param pCxPrivate JavaScript context. + * @param milliseconds Date specified as a UNIX timestamp in milliseconds + * (not seconds). If you have a JavaScript @c ​Date object, you can + * use @c ​Date.getTime() to obtain the UNIX time in milliseconds. + * @param formatString Date format string defined using ICU date formatting + * symbols. Usually, you internationalize the format string and + * get it translated before you pass it to + * FormatMillisecondsIntoDateString(). + * @return String containing the specified date with the specified date + * format. + * + * @sa http://en.wikipedia.org/wiki/Unix_time + * @sa https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table + */ + std::wstring FormatMillisecondsIntoDateStringGMT(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, const std::wstring& formatString); /** * Returns the specified floating-point number as a string, with the number