add gs
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"lint": {
|
||||
"LocalShadow": "fatal"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nonstrict"
|
||||
},
|
||||
"lint": {
|
||||
"ImplicitReturn": "fatal"
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
local Modules = game:GetService("CorePackages").AppTempCommon
|
||||
local Common = Modules.Common
|
||||
local Action = require(Common.Action)
|
||||
|
||||
return Action(script.Name, function(convo)
|
||||
return {
|
||||
conversation = convo,
|
||||
}
|
||||
end)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
local Modules = game:GetService("CorePackages").AppTempCommon
|
||||
|
||||
local Common = Modules.Common
|
||||
local Action = require(Common.Action)
|
||||
|
||||
return Action(script.Name, function(placeInfos)
|
||||
return {
|
||||
placeInfos = placeInfos,
|
||||
}
|
||||
end)
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
local Modules = game:GetService("CorePackages").AppTempCommon
|
||||
|
||||
local Action = require(Modules.Common.Action)
|
||||
local LuaDateTime = require(Modules.LuaChat.DateTime)
|
||||
|
||||
return Action(script.Name, function(userId,
|
||||
presence, lastLocation,
|
||||
placeId, rootPlaceId,
|
||||
gameInstanceId, lastOnlineISO, universeId, previousUniverseId)
|
||||
|
||||
local lastOnline = 0
|
||||
if lastOnlineISO ~= nil then
|
||||
local lastDateTime = LuaDateTime.fromIsoDate(lastOnlineISO)
|
||||
if lastDateTime ~= nil then
|
||||
lastOnline = lastDateTime:GetUnixTimestamp()
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
userId = userId,
|
||||
presence = presence,
|
||||
lastLocation = lastLocation,
|
||||
placeId = placeId,
|
||||
rootPlaceId = rootPlaceId,
|
||||
gameInstanceId = gameInstanceId,
|
||||
lastOnline = lastOnline,
|
||||
universeId = universeId,
|
||||
previousUniverseId = previousUniverseId,
|
||||
}
|
||||
end)
|
||||
@@ -0,0 +1,621 @@
|
||||
local LocalizationService = game:GetService("LocalizationService")
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
local GetFFlagUseDateTimeType = require(CorePackages.AppTempCommon.LuaApp.Flags.GetFFlagUseDateTimeType)
|
||||
|
||||
local FFlagChinaLicensingApp = settings():GetFFlag("ChinaLicensingApp")
|
||||
|
||||
--[[
|
||||
This is a Lua implementation of the DateTime API proposal. It'll eventually
|
||||
be implemented in C++ and merged into the rest of the codebase if this model
|
||||
of working with dates ends up being useful.
|
||||
]]
|
||||
|
||||
local TimeZone = require(script.Parent.TimeZone)
|
||||
local TimeUnit = require(script.Parent.TimeUnit)
|
||||
|
||||
local LuaDateTime = {}
|
||||
|
||||
local monthShortNames = {
|
||||
"Jan", "Feb", "Mar", "Apr",
|
||||
"May", "Jun", "Jul", "Aug",
|
||||
"Sep", "Oct", "Nov", "Dec"
|
||||
}
|
||||
|
||||
local monthLongNames = {
|
||||
"January", "February", "March", "April",
|
||||
"May", "June", "July", "August",
|
||||
"September", "October", "November", "December"
|
||||
}
|
||||
|
||||
local dayShortNames = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
}
|
||||
|
||||
local dayLongNames = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
}
|
||||
|
||||
--[[
|
||||
We structure tokens like this to preserve order, since Lua associative
|
||||
arrays have no inherent order.
|
||||
]]
|
||||
local tokens = {
|
||||
{"YYYY", function(values)
|
||||
return tostring(values.Year)
|
||||
end},
|
||||
{"MMMM", function(values)
|
||||
return monthLongNames[values.Month]
|
||||
end},
|
||||
{"MMM", function(values)
|
||||
return monthShortNames[values.Month]
|
||||
end},
|
||||
{"MM", function(values)
|
||||
return ("%02d"):format(values.Month)
|
||||
end},
|
||||
{"M", function(values)
|
||||
return tostring(values.Month)
|
||||
end},
|
||||
{"DDDD", function(values)
|
||||
return dayLongNames[values.WeekDay]
|
||||
end},
|
||||
{"DDD", function(values)
|
||||
return dayShortNames[values.WeekDay]
|
||||
end},
|
||||
{"DD", function(values)
|
||||
return ("%02d"):format(values.Day)
|
||||
end},
|
||||
{"D", function(values)
|
||||
return tostring(values.Day)
|
||||
end},
|
||||
{"HH", function(values)
|
||||
local hour = values.Hour
|
||||
|
||||
return ("%02d"):format(hour)
|
||||
end},
|
||||
{"H", function(values)
|
||||
local hour = values.Hour
|
||||
|
||||
return tostring(hour)
|
||||
end},
|
||||
{"hh", function(values)
|
||||
local hour = values.Hour % 12
|
||||
if hour == 0 then
|
||||
hour = 12
|
||||
end
|
||||
|
||||
return ("%02d"):format(hour)
|
||||
end},
|
||||
{"h", function(values)
|
||||
local hour = values.Hour % 12
|
||||
if hour == 0 then
|
||||
hour = 12
|
||||
end
|
||||
|
||||
return tostring(hour)
|
||||
end},
|
||||
{"mm", function(values)
|
||||
return ("%02d"):format(values.Minute)
|
||||
end},
|
||||
{"m", function(values)
|
||||
return tostring(values.Minute)
|
||||
end},
|
||||
{"ss", function(values)
|
||||
return ("%02d"):format(values.Seconds)
|
||||
end},
|
||||
{"s", function(values)
|
||||
return tostring(values.Seconds)
|
||||
end},
|
||||
{"A", function(values)
|
||||
if FFlagChinaLicensingApp then
|
||||
return values.Hour >= 12 and "下午" or "上午"
|
||||
else
|
||||
return values.Hour >= 12 and "PM" or "AM"
|
||||
end
|
||||
end},
|
||||
{"a", function(values)
|
||||
if FFlagChinaLicensingApp then
|
||||
return values.Hour >= 12 and "下午" or "上午"
|
||||
else
|
||||
return values.Hour >= 12 and "pm" or "am"
|
||||
end
|
||||
end}
|
||||
}
|
||||
|
||||
local tokenKeys = {}
|
||||
for _, pair in ipairs(tokens) do
|
||||
table.insert(tokenKeys, pair[1])
|
||||
end
|
||||
|
||||
local tokenMap = {}
|
||||
for _, pair in ipairs(tokens) do
|
||||
tokenMap[pair[1]] = pair[2]
|
||||
end
|
||||
|
||||
--[[
|
||||
What's the next token in this source?
|
||||
]]
|
||||
local function getToken(source, i)
|
||||
local char = source:sub(i, i)
|
||||
|
||||
for _, token in ipairs(tokenKeys) do
|
||||
-- Only keep checking if the first character matches the token
|
||||
if token:sub(1, 1) == char then
|
||||
local match = source:sub(i, i + token:len() - 1)
|
||||
|
||||
if match == token then
|
||||
return token
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
An estimate of the current time zone's offset from UTC in seconds.
|
||||
|
||||
This might fail for weird timezones (UTC +/- 14), but we can fix that by
|
||||
picking a reference time that's further away from the Unix epoch.
|
||||
]]
|
||||
local function getTimeZoneOffset()
|
||||
local actualEpoch = 86400 + 43200
|
||||
local epoch = os.time({year = 1970, month = 1, day = 2, isdst = -1})
|
||||
if epoch then
|
||||
return actualEpoch - epoch
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove all above functions and tables when clean up GetFFlagUseDateTimeType()
|
||||
|
||||
--[[
|
||||
Create a DateTime with the given values in UTC.
|
||||
|
||||
All values are optional!
|
||||
]]
|
||||
function LuaDateTime.new(year, month, day, hour, minute, seconds, milliseconds)
|
||||
if GetFFlagUseDateTimeType() then
|
||||
local self = {}
|
||||
self.dateTime = DateTime.fromUniversalTime(
|
||||
year or 1970,
|
||||
month or 1,
|
||||
day or 1,
|
||||
hour or 0,
|
||||
minute or 0,
|
||||
seconds or 0,
|
||||
milliseconds or 0)
|
||||
setmetatable(self, LuaDateTime)
|
||||
return self
|
||||
end
|
||||
|
||||
local tzOffset = getTimeZoneOffset()
|
||||
local timestamp = os.time({
|
||||
year = year or 1970,
|
||||
month = month or 1,
|
||||
day = day or 1,
|
||||
hour = hour or 0,
|
||||
min = minute or 0,
|
||||
sec = seconds or 0,
|
||||
isdst = -1
|
||||
})
|
||||
if timestamp == nil then
|
||||
timestamp = 0
|
||||
end
|
||||
|
||||
if seconds then
|
||||
local subseconds = seconds - math.floor(seconds)
|
||||
timestamp = timestamp + subseconds
|
||||
end
|
||||
|
||||
return LuaDateTime.fromUnixTimestamp(timestamp + tzOffset)
|
||||
end
|
||||
|
||||
--[[
|
||||
Create a DateTime representing now.
|
||||
]]
|
||||
function LuaDateTime.now()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
local self = {}
|
||||
self.dateTime = DateTime.now()
|
||||
setmetatable(self, LuaDateTime)
|
||||
return self
|
||||
end
|
||||
|
||||
return LuaDateTime.fromUnixTimestamp(os.time())
|
||||
end
|
||||
|
||||
--[[
|
||||
Create a Datetime from the given Unix timestamp.
|
||||
|
||||
Limited to the range [0, 2^32) when GetFFlagUseDateTimeType() is off, which lets us represent
|
||||
dates out to about 2038.
|
||||
|
||||
When GetFFlagUseDateTimeType() is on, year range is 1400-9999, and timestamp range is between
|
||||
first second of year 1400 to the last second of year 9999.
|
||||
]]
|
||||
function LuaDateTime.fromUnixTimestamp(timestamp)
|
||||
assert(type(timestamp) == "number", "Invalid argument #1 to fromUnixTimestamp, expected number.")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
local self = {}
|
||||
self.dateTime = DateTime.fromUnixTimestampMillis(timestamp*1000)
|
||||
setmetatable(self, LuaDateTime)
|
||||
return self
|
||||
end
|
||||
|
||||
local self = {}
|
||||
|
||||
self.value = timestamp
|
||||
|
||||
setmetatable(self, LuaDateTime)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--[[
|
||||
Attempt to create a DateTime from an ISO 8601 date-time string.
|
||||
|
||||
Will return nil on failure and output a warning to a console denoting what
|
||||
went wrong. This can probably turned into a second return value if we need
|
||||
to handle that data programmatically.
|
||||
]]
|
||||
function LuaDateTime.fromIsoDate(isoDate)
|
||||
assert(type(isoDate) == "string", "Invalid argument #1 to DateTime.fromIsoDate, expected string.")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
local self = {}
|
||||
self.dateTime = DateTime.fromIsoDate(isoDate)
|
||||
setmetatable(self, LuaDateTime)
|
||||
return self
|
||||
end
|
||||
|
||||
local datePattern = "^(%d+)%-(%d+)%-(%d+)" -- 0000-00-00
|
||||
local timePattern = "T(%d+):(%d+):(%d+%.?%d*)" -- T00:00:00
|
||||
local utcPattern = "Z$"
|
||||
local timeZonePattern = "([+-]%d+):(%d+)$" -- either Z or +/- followed by "00:00"
|
||||
|
||||
local timezone = 0
|
||||
local values = {1970, 1, 1, 0, 0, 0}
|
||||
local year, month, day = isoDate:match(datePattern)
|
||||
|
||||
if not year then
|
||||
warn(("Invalid ISO 8601 date: %q"):format(isoDate))
|
||||
return nil
|
||||
end
|
||||
|
||||
values[1] = tonumber(year)
|
||||
values[2] = tonumber(month)
|
||||
values[3] = tonumber(day)
|
||||
|
||||
local hour, minute, seconds = isoDate:match(timePattern)
|
||||
|
||||
if hour then
|
||||
values[4] = tonumber(hour)
|
||||
values[5] = tonumber(minute)
|
||||
values[6] = tonumber(seconds)
|
||||
|
||||
local isUtc = isoDate:match(utcPattern)
|
||||
|
||||
if not isUtc then
|
||||
local offsetHours, offsetMinutes = isoDate:match(timeZonePattern)
|
||||
|
||||
if not offsetHours then
|
||||
local offsetTotal = getTimeZoneOffset()
|
||||
offsetHours = offsetTotal / 3600
|
||||
offsetMinutes = 0
|
||||
|
||||
warn(("Invalid time zone in ISO 8601 date: %q -- falling back to local time"):format(isoDate))
|
||||
end
|
||||
|
||||
timezone = 3600 * tonumber(offsetHours) + 60 * tonumber(offsetMinutes)
|
||||
end
|
||||
end
|
||||
|
||||
local date = LuaDateTime.new(unpack(values))
|
||||
date.value = date.value - timezone
|
||||
|
||||
return date
|
||||
end
|
||||
|
||||
--[[
|
||||
Format our current date using a formatting string. Look at the DateTime
|
||||
proposal to see information about the different formatting tokens.
|
||||
Generally, they try to resemble LDML and/or Moment.js-style formatting.
|
||||
|
||||
The time zone parameter is optional and defaults to the current time zone,
|
||||
TimeZone.Current.
|
||||
]]
|
||||
function LuaDateTime:Format(formatString, tz, localeId)
|
||||
assert(type(formatString) == "string", "Invalid argument #1 to Format, expected string.")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
tz = tz or TimeZone.Current
|
||||
localeId = localeId or LocalizationService.RobloxLocaleId
|
||||
|
||||
if tz == TimeZone.UTC then
|
||||
return self.dateTime:FormatUniversalTime(formatString, localeId)
|
||||
elseif tz == TimeZone.Current then
|
||||
return self.dateTime:FormatLocalTime(formatString, localeId)
|
||||
else
|
||||
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
|
||||
end
|
||||
end
|
||||
|
||||
tz = tz or TimeZone.Current
|
||||
|
||||
local values = self:GetValues(tz)
|
||||
|
||||
local buffer = {}
|
||||
|
||||
local i = 1
|
||||
while i <= formatString:len() do
|
||||
local char = formatString:sub(i, i)
|
||||
local token = getToken(formatString, i)
|
||||
|
||||
if token then
|
||||
table.insert(buffer, tokenMap[token](values))
|
||||
i = i + token:len()
|
||||
elseif char == "[" then
|
||||
-- Crawl forward until the next ] and interpret that text literally
|
||||
local j = i
|
||||
while j <= formatString:len() do
|
||||
j = j + 1
|
||||
|
||||
if formatString:sub(j, j) == "]" then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(buffer, formatString:sub(i + 1, j - 1))
|
||||
i = j + 1
|
||||
else
|
||||
table.insert(buffer, char)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local result = table.concat(buffer)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--[[
|
||||
Get a table of values representing the date-time in the given timezone.
|
||||
|
||||
The time zone parameter is optional and defaults to the current zime zone,
|
||||
TimeZone.Current.
|
||||
|
||||
When GetFFlagUseDateTimeType() is true, table would include
|
||||
{Year, Month, Day, Hour, Minute, Second, Millisecond}
|
||||
]]
|
||||
function LuaDateTime:GetValues(tz)
|
||||
if GetFFlagUseDateTimeType() then
|
||||
tz = tz or TimeZone.Current
|
||||
|
||||
if tz == TimeZone.UTC then
|
||||
return self.dateTime:ToUniversalTime()
|
||||
elseif tz == TimeZone.Current then
|
||||
return self.dateTime:ToLocalTime()
|
||||
else
|
||||
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
|
||||
end
|
||||
end
|
||||
|
||||
tz = tz or TimeZone.Current
|
||||
|
||||
local reference
|
||||
|
||||
if tz == TimeZone.Current then
|
||||
reference = os.date("*t", self.value)
|
||||
elseif tz == TimeZone.UTC then
|
||||
reference = os.date("!*t", self.value)
|
||||
end
|
||||
|
||||
if not reference then
|
||||
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
|
||||
end
|
||||
|
||||
return {
|
||||
Year = reference.year,
|
||||
Month = reference.month,
|
||||
Day = reference.day,
|
||||
Hour = reference.hour,
|
||||
Minute = reference.min,
|
||||
Seconds = reference.sec,
|
||||
WeekDay = reference.wday
|
||||
}
|
||||
end
|
||||
|
||||
--[[
|
||||
Recover a Unix timestamp representing the DateTime's value.
|
||||
]]
|
||||
function LuaDateTime:GetUnixTimestamp()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
if self.dateTime:ToUniversalTime().Millisecond > 0 then
|
||||
return self.dateTime.UnixTimestamp + (self.dateTime.UnixTimestampMillis % 1000)/1000
|
||||
else
|
||||
return self.dateTime.UnixTimestamp
|
||||
end
|
||||
end
|
||||
|
||||
return self.value
|
||||
end
|
||||
|
||||
--[[
|
||||
Format the DateTime as an ISO 8601 date string with time attached.
|
||||
|
||||
Always formats the time as UTC. There generally aren't many reasons to
|
||||
generate an ISO 8601 date in another time zone.
|
||||
]]
|
||||
function LuaDateTime:GetIsoDate()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
return self.dateTime:ToIsoDate()
|
||||
end
|
||||
|
||||
return self:Format("YYYY-MM-DD[T]HH:mm:ss[Z]", TimeZone.UTC)
|
||||
end
|
||||
|
||||
-- Used by IsSame
|
||||
-- Remove when clean up GetFFlagUseDateTimeType()
|
||||
local descendingGranularityUnits = {
|
||||
{
|
||||
unit = TimeUnit.Years,
|
||||
key = "Year"
|
||||
},
|
||||
{
|
||||
unit = TimeUnit.Months,
|
||||
key = "Month"
|
||||
},
|
||||
{
|
||||
unit = TimeUnit.Days,
|
||||
key = "Day"
|
||||
},
|
||||
{
|
||||
unit = TimeUnit.Hours,
|
||||
key = "Hour"
|
||||
},
|
||||
{
|
||||
unit = TimeUnit.Minutes,
|
||||
key = "Minute"
|
||||
},
|
||||
{
|
||||
unit = TimeUnit.Seconds,
|
||||
key = "Seconds"
|
||||
}
|
||||
}
|
||||
|
||||
--[[
|
||||
Checks whether two DateTime values are the same, given a granularity and
|
||||
timezone value.
|
||||
|
||||
Granularity defaults to seconds and time zone defaults to the current local
|
||||
time zone.
|
||||
|
||||
Remove when clean up GetFFlagUseDateTimeType()
|
||||
]]
|
||||
function LuaDateTime:IsSame(other, granularity, timezone)
|
||||
granularity = granularity or TimeUnit.Seconds
|
||||
timezone = timezone or TimeZone.Current
|
||||
|
||||
local selfUnix = self:GetUnixTimestamp()
|
||||
local otherUnix = other:GetUnixTimestamp()
|
||||
|
||||
if selfUnix == otherUnix then
|
||||
return true
|
||||
end
|
||||
|
||||
local selfValues = self:GetValues(timezone)
|
||||
local otherValues = other:GetValues(timezone)
|
||||
|
||||
-- Week logic is special
|
||||
if granularity == TimeUnit.Weeks then
|
||||
local diff = math.abs(selfUnix - otherUnix)
|
||||
local diffDays = diff / (60 * 60 * 24)
|
||||
|
||||
-- Two dates separated by 7 or more whole days are never in the same week
|
||||
if diffDays >= 7 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Two dates separated by less than 7 days will be sorted monotonically
|
||||
-- if they're in the same week
|
||||
-- TODO: Use start-of-week value to shift WeekDay for locale
|
||||
if selfUnix > otherUnix then
|
||||
return selfValues.WeekDay >= otherValues.WeekDay
|
||||
else
|
||||
return selfValues.WeekDay <= otherValues.WeekDay
|
||||
end
|
||||
end
|
||||
|
||||
for _, unit in ipairs(descendingGranularityUnits) do
|
||||
local selfValue = selfValues[unit.key]
|
||||
local otherValue = otherValues[unit.key]
|
||||
|
||||
if selfValue ~= otherValue then
|
||||
return false
|
||||
end
|
||||
|
||||
if unit.unit == granularity then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
Get a human-readable timestamp relative to the given epoch, which defaults
|
||||
to now. The format of the time is contextual to how far away the times are.
|
||||
]]
|
||||
function LuaDateTime:GetLongRelativeTime(epoch, timezone, localeId)
|
||||
if GetFFlagUseDateTimeType() then
|
||||
-- Not relative time format for now, will do that later in DateTime v2
|
||||
return self:Format("lll", timezone, localeId)
|
||||
end
|
||||
|
||||
timezone = timezone or TimeZone.Current
|
||||
epoch = epoch or LuaDateTime.now()
|
||||
|
||||
if FFlagChinaLicensingApp then
|
||||
if self:IsSame(epoch, TimeUnit.Days, timezone) then
|
||||
return self:Format("HH:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
|
||||
return self:Format("M月D日 | HH:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
|
||||
return self:Format("M月D日 | HH:mm A", timezone)
|
||||
else
|
||||
return self:Format("YYYY年M月D日 | HH:mm A", timezone)
|
||||
end
|
||||
else
|
||||
if self:IsSame(epoch, TimeUnit.Days, timezone) then
|
||||
return self:Format("h:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
|
||||
return self:Format("DDD | h:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
|
||||
return self:Format("MMM D | h:mm A", timezone)
|
||||
else
|
||||
return self:Format("MMM D, YYYY | h:mm A", timezone)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Get a human-readable timestamp relative to the given epoch, which defaults
|
||||
to now. The format of the time is contextual to how far away the times are.
|
||||
]]
|
||||
function LuaDateTime:GetShortRelativeTime(epoch, timezone, localeId)
|
||||
timezone = timezone or TimeZone.Current
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
-- Not relative time format for now, will do that later in DateTime v2
|
||||
return self:Format("ll", timezone, localeId)
|
||||
end
|
||||
|
||||
epoch = epoch or LuaDateTime.now()
|
||||
|
||||
if FFlagChinaLicensingApp then
|
||||
if self:IsSame(epoch, TimeUnit.Days, timezone) then
|
||||
return self:Format("HH:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
|
||||
return self:Format("M月D日", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
|
||||
return self:Format("M月D日", timezone)
|
||||
else
|
||||
return self:Format("YYYY年M月D日", timezone)
|
||||
end
|
||||
else
|
||||
if self:IsSame(epoch, TimeUnit.Days, timezone) then
|
||||
return self:Format("h:mm A", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
|
||||
return self:Format("DDD", timezone)
|
||||
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
|
||||
return self:Format("MMM D", timezone)
|
||||
else
|
||||
return self:Format("MMM D, YYYY", timezone)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
LuaDateTime.__index = LuaDateTime
|
||||
|
||||
return LuaDateTime
|
||||
@@ -0,0 +1,738 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
local GetFFlagUseDateTimeType = require(CorePackages.AppTempCommon.LuaApp.Flags.GetFFlagUseDateTimeType)
|
||||
local FFlagChinaLicensingApp = settings():GetFFlag("ChinaLicensingApp")
|
||||
|
||||
return function()
|
||||
local LuaDateTime = require(script.Parent.DateTime)
|
||||
local TimeZone = require(script.Parent.TimeZone)
|
||||
local TimeUnit = require(script.Parent.TimeUnit)
|
||||
local localeIds = {
|
||||
"en-us",
|
||||
"en-gb",
|
||||
"en-au",
|
||||
"en-ca",
|
||||
"en-nz",
|
||||
"de-de",
|
||||
"es-es",
|
||||
"es-mx",
|
||||
"fr-fr",
|
||||
"fr-ca",
|
||||
"it-it",
|
||||
"pt-pt",
|
||||
"pt-br",
|
||||
"ru-ru",
|
||||
"ja-jp",
|
||||
"ko-kr",
|
||||
"zh-cn",
|
||||
"zh-hk",
|
||||
"zh-tw",
|
||||
"zh-hans",
|
||||
"zh-hant",
|
||||
"zh-cjv",
|
||||
}
|
||||
|
||||
describe("Constructors", function()
|
||||
it("should construct with 'new'", function()
|
||||
expect(LuaDateTime.new()).to.be.ok()
|
||||
expect(LuaDateTime.new(2017)).to.be.ok()
|
||||
expect(LuaDateTime.new(2017, 5)).to.be.ok()
|
||||
expect(LuaDateTime.new(2017, 5, 3)).to.be.ok()
|
||||
expect(LuaDateTime.new(2017, 5, 3, 12)).to.be.ok()
|
||||
expect(LuaDateTime.new(2017, 5, 3, 12, 34)).to.be.ok()
|
||||
expect(LuaDateTime.new(2017, 5, 3, 12, 34, 51)).to.be.ok()
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(LuaDateTime.new(2017, 5, 3, 12, 34, 51, 999)).to.be.ok()
|
||||
end
|
||||
end)
|
||||
|
||||
it("should construct with 'now'", function()
|
||||
expect(LuaDateTime.now()).to.be.ok()
|
||||
end)
|
||||
|
||||
it("should construct from a Unix timestamp", function()
|
||||
expect(LuaDateTime.fromUnixTimestamp(0)).to.be.ok()
|
||||
expect(LuaDateTime.fromUnixTimestamp(os.time())).to.be.ok()
|
||||
end)
|
||||
|
||||
it("should construct from an ISO 8601 date", function()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
-- Basic date
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("1988-03-17")
|
||||
expect(date).to.be.ok()
|
||||
expect(date.dateTime:ToUniversalTime().Year).to.equal(1988)
|
||||
expect(date.dateTime:ToUniversalTime().Month).to.equal(3)
|
||||
expect(date.dateTime:ToUniversalTime().Day).to.equal(17)
|
||||
expect(date.dateTime:ToUniversalTime().Hour).to.equal(0)
|
||||
expect(date.dateTime:ToUniversalTime().Minute).to.equal(0)
|
||||
expect(date.dateTime:ToUniversalTime().Second).to.equal(0)
|
||||
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
|
||||
end
|
||||
|
||||
-- Date and time
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16.999Z")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816.999)
|
||||
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
|
||||
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
|
||||
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
|
||||
expect(date.dateTime:ToUniversalTime().Hour).to.equal(20)
|
||||
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
|
||||
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
|
||||
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(999)
|
||||
end
|
||||
|
||||
-- Date and time with no time zone
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16.1")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816.1)
|
||||
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
|
||||
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
|
||||
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
|
||||
expect(date.dateTime:ToUniversalTime().Hour).to.equal(20)
|
||||
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
|
||||
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
|
||||
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(100)
|
||||
end
|
||||
|
||||
-- Date, time, and time zone offset
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16+01:00")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816 - 3600)
|
||||
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
|
||||
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
|
||||
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
|
||||
expect(date.dateTime:ToUniversalTime().Hour).to.equal(19)
|
||||
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
|
||||
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
|
||||
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
|
||||
end
|
||||
|
||||
-- Date, time, and negative time zone offset
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16-01:00")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816 + 3600)
|
||||
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
|
||||
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
|
||||
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
|
||||
expect(date.dateTime:ToUniversalTime().Hour).to.equal(21)
|
||||
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
|
||||
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
|
||||
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
|
||||
end
|
||||
else
|
||||
-- Basic date
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("1988-03-17")
|
||||
expect(date).to.be.ok()
|
||||
end
|
||||
|
||||
-- Date and time
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16Z")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816)
|
||||
end
|
||||
|
||||
-- Date and time with no time zone
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16")
|
||||
expect(date).to.be.ok()
|
||||
end
|
||||
|
||||
-- Date, time, and time zone offset
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16+01:00")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816 - 3600)
|
||||
end
|
||||
|
||||
-- Date, time, and negative time zone offset
|
||||
do
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16-01:00")
|
||||
expect(date).to.be.ok()
|
||||
expect(date:GetUnixTimestamp()).to.equal(1491856816 + 3600)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Measurements", function()
|
||||
it("should get values in UTC", function()
|
||||
local date = LuaDateTime.new()
|
||||
local values = date:GetValues(TimeZone.UTC)
|
||||
|
||||
expect(values).to.be.ok()
|
||||
expect(values.Year).to.be.a("number")
|
||||
expect(values.Month).to.be.a("number")
|
||||
expect(values.Day).to.be.a("number")
|
||||
expect(values.Hour).to.be.a("number")
|
||||
expect(values.Minute).to.be.a("number")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(values.Second).to.be.a("number")
|
||||
expect(values.Millisecond).to.be.a("number")
|
||||
else
|
||||
expect(values.Seconds).to.be.a("number")
|
||||
|
||||
-- Locale specific!
|
||||
expect(values.WeekDay).to.be.a("number")
|
||||
end
|
||||
end)
|
||||
|
||||
it("should get values in local time", function()
|
||||
local date = LuaDateTime.new()
|
||||
local values = date:GetValues(TimeZone.Current)
|
||||
|
||||
expect(values).to.be.ok()
|
||||
expect(values.Year).to.be.a("number")
|
||||
expect(values.Month).to.be.a("number")
|
||||
expect(values.Day).to.be.a("number")
|
||||
expect(values.Hour).to.be.a("number")
|
||||
expect(values.Minute).to.be.a("number")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(values.Second).to.be.a("number")
|
||||
expect(values.Millisecond).to.be.a("number")
|
||||
else
|
||||
expect(values.Seconds).to.be.a("number")
|
||||
|
||||
-- Locale specific!
|
||||
expect(values.WeekDay).to.be.a("number")
|
||||
end
|
||||
end)
|
||||
|
||||
it("should preserve values from 'new' constructor", function()
|
||||
local date = LuaDateTime.new(2017, 11, 3, 12, 34, 51)
|
||||
local values = date:GetValues(TimeZone.UTC)
|
||||
|
||||
expect(values.Year).to.equal(2017)
|
||||
expect(values.Month).to.equal(11)
|
||||
expect(values.Day).to.equal(3)
|
||||
expect(values.Hour).to.equal(12)
|
||||
expect(values.Minute).to.equal(34)
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(values.Second).to.equal(51)
|
||||
expect(values.Millisecond).to.equal(0)
|
||||
else
|
||||
expect(values.Seconds).to.equal(51)
|
||||
end
|
||||
end)
|
||||
|
||||
it("should preserve Unix timestamp values", function()
|
||||
do
|
||||
local date = LuaDateTime.fromUnixTimestamp(0)
|
||||
expect(date:GetUnixTimestamp()).to.equal(0)
|
||||
end
|
||||
|
||||
do
|
||||
local date = LuaDateTime.fromUnixTimestamp(123456789)
|
||||
expect(date:GetUnixTimestamp()).to.equal(123456789)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Formatting", function()
|
||||
it("should preserve text within brackets", function()
|
||||
local date = LuaDateTime.new(2017, 1, 2, 15, 8, 9)
|
||||
|
||||
local function format(str)
|
||||
return date:Format(str, TimeZone.UTC)
|
||||
end
|
||||
|
||||
expect(format("[Hello, world!]")).to.equal("Hello, world!")
|
||||
expect(format("[YYYY-MM-DD]")).to.equal("YYYY-MM-DD")
|
||||
end)
|
||||
|
||||
it("should create identical ISO 8601 dates for UTC inputs", function()
|
||||
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16Z")
|
||||
expect(date:GetIsoDate()).to.equal("2017-04-10T20:40:16Z")
|
||||
end)
|
||||
|
||||
it("should have correct formatting tokens", function()
|
||||
local date = LuaDateTime.new(2016, 1, 2, 15, 8, 9)
|
||||
|
||||
-- Shortcut time zone specification
|
||||
local function format(str, localeId)
|
||||
return date:Format(str, TimeZone.UTC, localeId)
|
||||
end
|
||||
|
||||
expect(format("YYYY")).to.equal("2016")
|
||||
expect(format("M")).to.equal("1")
|
||||
expect(format("MM")).to.equal("01")
|
||||
expect(format("D")).to.equal("2")
|
||||
expect(format("DD")).to.equal("02")
|
||||
expect(format("H")).to.equal("15")
|
||||
expect(format("HH")).to.equal("15")
|
||||
expect(format("h")).to.equal("3")
|
||||
expect(format("hh")).to.equal("03")
|
||||
expect(format("m")).to.equal("8")
|
||||
expect(format("mm")).to.equal("08")
|
||||
expect(format("s")).to.equal("9")
|
||||
expect(format("ss")).to.equal("09")
|
||||
|
||||
-- Locale-specific tests!
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(format("SSS")).to.equal("000")
|
||||
expect(format("SS")).to.equal("00")
|
||||
expect(format("S")).to.equal("0")
|
||||
expect(format("MMM", "en-us")).to.equal("Jan")
|
||||
expect(format("MMMM", "en-us")).to.equal("January")
|
||||
expect(format("MMM", "zh-cn")).to.equal("1月")
|
||||
expect(format("MMMM", "zh-cn")).to.equal("一月")
|
||||
expect(format("A", "en-us")).to.equal("PM")
|
||||
expect(format("a", "en-us")).to.equal("pm")
|
||||
expect(format("A", "zh-cn")).to.equal("下午")
|
||||
expect(format("a", "zh-cn")).to.equal("下午")
|
||||
else
|
||||
expect(format("MMM")).to.equal("Jan")
|
||||
expect(format("MMMM")).to.equal("January")
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(format("A")).to.equal("下午")
|
||||
expect(format("a")).to.equal("下午")
|
||||
else
|
||||
expect(format("A")).to.equal("PM")
|
||||
expect(format("a")).to.equal("pm")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
it("should handle dates around midnight", function()
|
||||
local date = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
|
||||
expect(date:Format("H", TimeZone.UTC)).to.equal("0")
|
||||
expect(date:Format("HH", TimeZone.UTC)).to.equal("00")
|
||||
expect(date:Format("h", TimeZone.UTC)).to.equal("12")
|
||||
expect(date:Format("hh", TimeZone.UTC)).to.equal("12")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(date:Format("A", TimeZone.UTC, "en-us")).to.equal("AM")
|
||||
expect(date:Format("a", TimeZone.UTC, "en-us")).to.equal("am")
|
||||
expect(date:Format("A", TimeZone.UTC, "zh-cn")).to.equal("凌晨")
|
||||
expect(date:Format("a", TimeZone.UTC, "zh-cn")).to.equal("凌晨")
|
||||
else
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:Format("a", TimeZone.UTC)).to.equal("上午")
|
||||
else
|
||||
expect(date:Format("a", TimeZone.UTC)).to.equal("am")
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
it("should handle dates around noon", function()
|
||||
local date = LuaDateTime.new(2017, 5, 23, 12, 0, 0)
|
||||
|
||||
expect(date:Format("H", TimeZone.UTC)).to.equal("12")
|
||||
expect(date:Format("HH", TimeZone.UTC)).to.equal("12")
|
||||
expect(date:Format("h", TimeZone.UTC)).to.equal("12")
|
||||
expect(date:Format("hh", TimeZone.UTC)).to.equal("12")
|
||||
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expect(date:Format("A", TimeZone.UTC, "en-us")).to.equal("PM")
|
||||
expect(date:Format("a", TimeZone.UTC, "en-us")).to.equal("pm")
|
||||
expect(date:Format("A", TimeZone.UTC, "zh-cn")).to.equal("中午")
|
||||
expect(date:Format("a", TimeZone.UTC, "zh-cn")).to.equal("中午")
|
||||
else
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:Format("a", TimeZone.UTC)).to.equal("下午")
|
||||
else
|
||||
expect(date:Format("a", TimeZone.UTC)).to.equal("pm")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
it("should return correct 24-hour clock sequences", function()
|
||||
local expected = {
|
||||
"2017-09-13 00:00:00",
|
||||
"2017-09-13 01:00:00",
|
||||
"2017-09-13 02:00:00",
|
||||
"2017-09-13 03:00:00",
|
||||
"2017-09-13 04:00:00",
|
||||
"2017-09-13 05:00:00",
|
||||
"2017-09-13 06:00:00",
|
||||
"2017-09-13 07:00:00",
|
||||
"2017-09-13 08:00:00",
|
||||
"2017-09-13 09:00:00",
|
||||
"2017-09-13 10:00:00",
|
||||
"2017-09-13 11:00:00",
|
||||
"2017-09-13 12:00:00",
|
||||
"2017-09-13 13:00:00",
|
||||
"2017-09-13 14:00:00",
|
||||
"2017-09-13 15:00:00",
|
||||
"2017-09-13 16:00:00",
|
||||
"2017-09-13 17:00:00",
|
||||
"2017-09-13 18:00:00",
|
||||
"2017-09-13 19:00:00",
|
||||
"2017-09-13 20:00:00",
|
||||
"2017-09-13 21:00:00",
|
||||
"2017-09-13 22:00:00",
|
||||
"2017-09-13 23:00:00",
|
||||
"2017-09-14 00:00:00",
|
||||
"2017-09-14 01:00:00",
|
||||
}
|
||||
|
||||
local formatString = "YYYY-MM-DD HH:mm:ss"
|
||||
local date
|
||||
|
||||
for _, localeId in ipairs(localeIds) do
|
||||
date = LuaDateTime.new(2017, 9, 13, 0, 0, 0)
|
||||
for i = 1, #expected do
|
||||
local result = date:Format(formatString, TimeZone.UTC, localeId)
|
||||
expect(result).to.equal(expected[i])
|
||||
|
||||
-- Advance once hour
|
||||
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
it("should return correct 12-hour clock sequences", function()
|
||||
local date = LuaDateTime.new(2017, 9, 13, 0, 0, 0)
|
||||
|
||||
local formatString = "YYYY-MM-DD hh:mm:ss a"
|
||||
|
||||
local expected
|
||||
if GetFFlagUseDateTimeType() then
|
||||
expected = {
|
||||
["en-us"] = {
|
||||
"2017-09-13 12:00:00 am",
|
||||
"2017-09-13 01:00:00 am",
|
||||
"2017-09-13 02:00:00 am",
|
||||
"2017-09-13 03:00:00 am",
|
||||
"2017-09-13 04:00:00 am",
|
||||
"2017-09-13 05:00:00 am",
|
||||
"2017-09-13 06:00:00 am",
|
||||
"2017-09-13 07:00:00 am",
|
||||
"2017-09-13 08:00:00 am",
|
||||
"2017-09-13 09:00:00 am",
|
||||
"2017-09-13 10:00:00 am",
|
||||
"2017-09-13 11:00:00 am",
|
||||
"2017-09-13 12:00:00 pm",
|
||||
"2017-09-13 01:00:00 pm",
|
||||
"2017-09-13 02:00:00 pm",
|
||||
"2017-09-13 03:00:00 pm",
|
||||
"2017-09-13 04:00:00 pm",
|
||||
"2017-09-13 05:00:00 pm",
|
||||
"2017-09-13 06:00:00 pm",
|
||||
"2017-09-13 07:00:00 pm",
|
||||
"2017-09-13 08:00:00 pm",
|
||||
"2017-09-13 09:00:00 pm",
|
||||
"2017-09-13 10:00:00 pm",
|
||||
"2017-09-13 11:00:00 pm",
|
||||
"2017-09-14 12:00:00 am",
|
||||
"2017-09-14 01:00:00 am",
|
||||
},
|
||||
["zh-cn"] = {
|
||||
"2017-09-13 12:00:00 凌晨",
|
||||
"2017-09-13 01:00:00 凌晨",
|
||||
"2017-09-13 02:00:00 凌晨",
|
||||
"2017-09-13 03:00:00 凌晨",
|
||||
"2017-09-13 04:00:00 凌晨",
|
||||
"2017-09-13 05:00:00 凌晨",
|
||||
"2017-09-13 06:00:00 早上",
|
||||
"2017-09-13 07:00:00 早上",
|
||||
"2017-09-13 08:00:00 早上",
|
||||
"2017-09-13 09:00:00 上午",
|
||||
"2017-09-13 10:00:00 上午",
|
||||
"2017-09-13 11:00:00 上午",
|
||||
"2017-09-13 12:00:00 中午",
|
||||
"2017-09-13 01:00:00 下午",
|
||||
"2017-09-13 02:00:00 下午",
|
||||
"2017-09-13 03:00:00 下午",
|
||||
"2017-09-13 04:00:00 下午",
|
||||
"2017-09-13 05:00:00 下午",
|
||||
"2017-09-13 06:00:00 晚上",
|
||||
"2017-09-13 07:00:00 晚上",
|
||||
"2017-09-13 08:00:00 晚上",
|
||||
"2017-09-13 09:00:00 晚上",
|
||||
"2017-09-13 10:00:00 晚上",
|
||||
"2017-09-13 11:00:00 晚上",
|
||||
"2017-09-14 12:00:00 凌晨",
|
||||
"2017-09-14 01:00:00 凌晨",
|
||||
}
|
||||
}
|
||||
|
||||
for i = 1, #expected do
|
||||
for j = 1, #expected[i] do
|
||||
local result = date:Format(formatString, TimeZone.UTC, expected[i])
|
||||
expect(result).to.equal(expected[i][j])
|
||||
|
||||
-- Advance once hour
|
||||
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
|
||||
end
|
||||
end
|
||||
else
|
||||
if FFlagChinaLicensingApp then
|
||||
expected = {
|
||||
"2017-09-13 12:00:00 上午",
|
||||
"2017-09-13 01:00:00 上午",
|
||||
"2017-09-13 02:00:00 上午",
|
||||
"2017-09-13 03:00:00 上午",
|
||||
"2017-09-13 04:00:00 上午",
|
||||
"2017-09-13 05:00:00 上午",
|
||||
"2017-09-13 06:00:00 上午",
|
||||
"2017-09-13 07:00:00 上午",
|
||||
"2017-09-13 08:00:00 上午",
|
||||
"2017-09-13 09:00:00 上午",
|
||||
"2017-09-13 10:00:00 上午",
|
||||
"2017-09-13 11:00:00 上午",
|
||||
"2017-09-13 12:00:00 下午",
|
||||
"2017-09-13 01:00:00 下午",
|
||||
"2017-09-13 02:00:00 下午",
|
||||
"2017-09-13 03:00:00 下午",
|
||||
"2017-09-13 04:00:00 下午",
|
||||
"2017-09-13 05:00:00 下午",
|
||||
"2017-09-13 06:00:00 下午",
|
||||
"2017-09-13 07:00:00 下午",
|
||||
"2017-09-13 08:00:00 下午",
|
||||
"2017-09-13 09:00:00 下午",
|
||||
"2017-09-13 10:00:00 下午",
|
||||
"2017-09-13 11:00:00 下午",
|
||||
"2017-09-14 12:00:00 上午",
|
||||
"2017-09-14 01:00:00 上午",
|
||||
}
|
||||
else
|
||||
expected = {
|
||||
"2017-09-13 12:00:00 am",
|
||||
"2017-09-13 01:00:00 am",
|
||||
"2017-09-13 02:00:00 am",
|
||||
"2017-09-13 03:00:00 am",
|
||||
"2017-09-13 04:00:00 am",
|
||||
"2017-09-13 05:00:00 am",
|
||||
"2017-09-13 06:00:00 am",
|
||||
"2017-09-13 07:00:00 am",
|
||||
"2017-09-13 08:00:00 am",
|
||||
"2017-09-13 09:00:00 am",
|
||||
"2017-09-13 10:00:00 am",
|
||||
"2017-09-13 11:00:00 am",
|
||||
"2017-09-13 12:00:00 pm",
|
||||
"2017-09-13 01:00:00 pm",
|
||||
"2017-09-13 02:00:00 pm",
|
||||
"2017-09-13 03:00:00 pm",
|
||||
"2017-09-13 04:00:00 pm",
|
||||
"2017-09-13 05:00:00 pm",
|
||||
"2017-09-13 06:00:00 pm",
|
||||
"2017-09-13 07:00:00 pm",
|
||||
"2017-09-13 08:00:00 pm",
|
||||
"2017-09-13 09:00:00 pm",
|
||||
"2017-09-13 10:00:00 pm",
|
||||
"2017-09-13 11:00:00 pm",
|
||||
"2017-09-14 12:00:00 am",
|
||||
"2017-09-14 01:00:00 am",
|
||||
}
|
||||
end
|
||||
|
||||
for i = 1, #expected do
|
||||
local result = date:Format(formatString, TimeZone.UTC)
|
||||
expect(result).to.equal(expected[i])
|
||||
|
||||
-- Advance once hour
|
||||
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
describe("LongRelativeTime", function()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
it("SHOULD handle UTC time correctly with different locales", function()
|
||||
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
|
||||
for _, localeId in ipairs(localeIds) do
|
||||
local longRelativeTime = date:GetLongRelativeTime(date, TimeZone.UTC, localeId)
|
||||
expect(longRelativeTime).to.equal(date.dateTime:FormatUniversalTime("lll", localeId))
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle Local time correctly with different locales", function()
|
||||
local date = LuaDateTime.fromUnixTimestamp(DateTime.fromLocalTime(2015, 4, 20, 13, 0, 0).UnixTimestamp)
|
||||
for _, localeId in ipairs(localeIds) do
|
||||
local longRelativeTime = date:GetLongRelativeTime(date, TimeZone.Current, localeId)
|
||||
expect(longRelativeTime).to.equal(date.dateTime:FormatLocalTime("lll", localeId))
|
||||
end
|
||||
end)
|
||||
else
|
||||
it("SHOULD handle same day case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
|
||||
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("13:00 下午")
|
||||
else
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle same week case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 4, 19, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("4月19日 | 13:00 下午")
|
||||
else
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Sun | 1:00 PM")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle same year case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 1, 20, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("1月20日 | 13:00 下午")
|
||||
else
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20 | 1:00 PM")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle different year case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2010, 1, 20, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("2010年1月20日 | 13:00 下午")
|
||||
else
|
||||
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010 | 1:00 PM")
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
describe("ShortRelativeTime", function()
|
||||
if GetFFlagUseDateTimeType() then
|
||||
it("SHOULD handle UTC time correctly with different locales", function()
|
||||
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
|
||||
for _, localeId in ipairs(localeIds) do
|
||||
local shortRelativeTime = date:GetShortRelativeTime(date, TimeZone.UTC, localeId)
|
||||
expect(shortRelativeTime).to.equal(date.dateTime:FormatUniversalTime("ll", localeId))
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle Local time correctly with different locales", function()
|
||||
local date = LuaDateTime.fromUnixTimestamp(DateTime.fromLocalTime(2015, 4, 20, 13, 0, 0).UnixTimestamp)
|
||||
for _, localeId in ipairs(localeIds) do
|
||||
local shortRelativeTime = date:GetShortRelativeTime(date, TimeZone.Current, localeId)
|
||||
expect(shortRelativeTime).to.equal(date.dateTime:FormatLocalTime("ll", localeId))
|
||||
end
|
||||
end)
|
||||
else
|
||||
it("SHOULD handle same day case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("13:00 下午")
|
||||
else
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle same week case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 4, 19, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("4月19日")
|
||||
else
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Sun")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle same year case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2015, 1, 20, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("1月20日")
|
||||
else
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20")
|
||||
end
|
||||
end)
|
||||
|
||||
it("SHOULD handle different year case", function()
|
||||
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
|
||||
local date = LuaDateTime.new(2010, 1, 20, 13, 0, 0)
|
||||
if FFlagChinaLicensingApp then
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("2010年1月20日")
|
||||
else
|
||||
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010")
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
if not GetFFlagUseDateTimeType() then
|
||||
describe("Comparisons", function()
|
||||
describe("IsSame", function()
|
||||
it("should equate dates with different granularity", function()
|
||||
local value = LuaDateTime.new(2003, 6, 11, 15, 8, 9)
|
||||
local same = LuaDateTime.new(2003, 6, 11, 15, 8, 9)
|
||||
|
||||
expect(value:IsSame(value)).to.equal(true)
|
||||
expect(value:IsSame(same)).to.equal(true)
|
||||
|
||||
local units = {TimeUnit.Years, TimeUnit.Months, TimeUnit.Days, TimeUnit.Hours, TimeUnit.Minutes}
|
||||
for _, unit in ipairs(units) do
|
||||
expect(value:IsSame(same, unit)).to.equal(true)
|
||||
end
|
||||
|
||||
local sameMinute = LuaDateTime.new(2003, 6, 11, 15, 8, 10)
|
||||
|
||||
expect(value:IsSame(sameMinute)).to.equal(false)
|
||||
expect(value:IsSame(sameMinute, TimeUnit.Minutes)).to.equal(true)
|
||||
expect(value:IsSame(sameMinute, TimeUnit.Years)).to.equal(true)
|
||||
|
||||
local sameHour = LuaDateTime.new(2003, 6, 11, 15, 9, 0)
|
||||
|
||||
expect(value:IsSame(sameHour)).to.equal(false)
|
||||
expect(value:IsSame(sameHour, TimeUnit.Hours)).to.equal(true)
|
||||
expect(value:IsSame(sameHour, TimeUnit.Years)).to.equal(true)
|
||||
|
||||
local sameDay = LuaDateTime.new(2003, 6, 11, 14, 8, 9)
|
||||
|
||||
expect(value:IsSame(sameDay)).to.equal(false)
|
||||
expect(value:IsSame(sameDay, TimeUnit.Days)).to.equal(true)
|
||||
expect(value:IsSame(sameDay, TimeUnit.Years)).to.equal(true)
|
||||
|
||||
local sameMonth = LuaDateTime.new(2003, 6, 12, 15, 8, 9)
|
||||
|
||||
expect(value:IsSame(sameMonth)).to.equal(false)
|
||||
expect(value:IsSame(sameMonth, TimeUnit.Months)).to.equal(true)
|
||||
expect(value:IsSame(sameMonth, TimeUnit.Years)).to.equal(true)
|
||||
|
||||
local sameYear = LuaDateTime.new(2003, 7, 12, 15, 8, 9)
|
||||
|
||||
expect(value:IsSame(sameYear)).to.equal(false)
|
||||
expect(value:IsSame(sameYear, TimeUnit.Years)).to.equal(true)
|
||||
|
||||
local diffYear = LuaDateTime.new(2004, 6, 11, 15, 8, 9)
|
||||
|
||||
expect(value:IsSame(diffYear)).to.equal(false)
|
||||
expect(value:IsSame(diffYear, TimeUnit.Years)).to.equal(false)
|
||||
end)
|
||||
|
||||
it("should equate values using week boundaries", function()
|
||||
local sunday = LuaDateTime.new(2017, 5, 7)
|
||||
local saturday = LuaDateTime.new(2017, 5, 13)
|
||||
local monday = LuaDateTime.new(2017, 5, 8)
|
||||
local tuesday = LuaDateTime.new(2017, 5, 9)
|
||||
|
||||
-- TODO: Specify locale when that lands; default may break tests
|
||||
local function sameWeek(a, b)
|
||||
return a:IsSame(b, TimeUnit.Weeks, TimeZone.UTC)
|
||||
end
|
||||
|
||||
expect(sameWeek(monday, monday)).to.equal(true)
|
||||
|
||||
expect(sameWeek(sunday, monday)).to.equal(true)
|
||||
expect(sameWeek(tuesday, monday)).to.equal(true)
|
||||
expect(sameWeek(saturday, monday)).to.equal(true)
|
||||
|
||||
local nextSunday = LuaDateTime.new(2017, 5, 14)
|
||||
|
||||
expect(sameWeek(nextSunday, monday)).to.equal(false)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nonstrict"
|
||||
},
|
||||
"lint": {
|
||||
"ImplicitReturn": "fatal"
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
local Players = game:GetService("Players")
|
||||
local ThrottleUserId = require(CorePackages.AppTempCommon.LuaApp.Utils.ThrottleUserId)
|
||||
|
||||
return function()
|
||||
return ThrottleUserId(
|
||||
game:DefineFastInt("LuaChatUseNewFriendsEndpointsV2", 0),
|
||||
Players.LocalPlayer.UserId
|
||||
)
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nonstrict"
|
||||
},
|
||||
"lint": {
|
||||
"ImplicitReturn": "fatal"
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
|
||||
local MockId = require(CorePackages.AppTempCommon.LuaApp.MockId)
|
||||
|
||||
local FFlagLuaAppConvertUniverseIdToString = settings():GetFFlag("LuaAppConvertUniverseIdToStringV364")
|
||||
|
||||
local PlaceInfoModel = {}
|
||||
|
||||
function PlaceInfoModel.new()
|
||||
local self = {}
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PlaceInfoModel.mock()
|
||||
local self = PlaceInfoModel.new()
|
||||
|
||||
self.builder = "builder"
|
||||
self.builderId = MockId()
|
||||
self.description = "description"
|
||||
self.imageToken = MockId()
|
||||
self.isPlayable = true
|
||||
self.name = "name"
|
||||
self.placeId = MockId()
|
||||
self.price = 0
|
||||
self.reasonProhibited = nil
|
||||
self.universeId = MockId()
|
||||
self.universeRootPlaceId = MockId()
|
||||
self.url = "url"
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PlaceInfoModel.fromWeb(data)
|
||||
local self = data or {}
|
||||
self.placeId = tostring(self.placeId)
|
||||
|
||||
if FFlagLuaAppConvertUniverseIdToString then
|
||||
self.universeId = tostring(self.universeId)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return PlaceInfoModel
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nonstrict"
|
||||
},
|
||||
"lint": {
|
||||
"ImplicitReturn": "fatal"
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
local SetFriendCount = require(CorePackages.AppTempCommon.LuaApp.Actions.SetFriendCount)
|
||||
|
||||
return function(state, action)
|
||||
state = state or 0
|
||||
|
||||
if action.type == SetFriendCount.name then
|
||||
state = action.count
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
return function()
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
local FriendCount = require(CorePackages.AppTempCommon.LuaChat.Reducers.FriendCount)
|
||||
local SetFriendCount = require(CorePackages.AppTempCommon.LuaApp.Actions.SetFriendCount)
|
||||
|
||||
it("should be zero by default", function()
|
||||
local state = FriendCount(nil, {})
|
||||
|
||||
expect(state).to.equal(0)
|
||||
end)
|
||||
|
||||
it("should respond to SetFriendCount", function()
|
||||
local state = FriendCount(nil, {})
|
||||
state = FriendCount(state, SetFriendCount(520))
|
||||
|
||||
expect(state).to.equal(520)
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
|
||||
local Common = CorePackages.AppTempCommon.Common
|
||||
local LuaChat = CorePackages.AppTempCommon.LuaChat
|
||||
|
||||
local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
|
||||
|
||||
local Immutable = require(Common.Immutable)
|
||||
|
||||
return function(state, action)
|
||||
state = state or {}
|
||||
if action.type == ReceivedMultiplePlaceInfos.name then
|
||||
|
||||
local newInfos = {}
|
||||
for _, placeInfo in ipairs(action.placeInfos) do
|
||||
newInfos[placeInfo.placeId] = placeInfo
|
||||
end
|
||||
|
||||
state = Immutable.JoinDictionaries(state, newInfos)
|
||||
end
|
||||
return state
|
||||
end
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
return function()
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
|
||||
local LuaApp = CorePackages.AppTempCommon.LuaApp
|
||||
local LuaChat = CorePackages.AppTempCommon.LuaChat
|
||||
|
||||
local MockId = require(LuaApp.MockId)
|
||||
local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
|
||||
|
||||
local PlaceInfosReducer = require(script.Parent.PlaceInfos)
|
||||
|
||||
describe("initial state", function()
|
||||
it("should return an initial table when passed nil", function()
|
||||
local state = PlaceInfosReducer(nil, {})
|
||||
expect(state).to.be.a("table")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("ReceivedMultiplePlaceInfos", function()
|
||||
it("should add place info to the store", function()
|
||||
local state = PlaceInfosReducer(nil, {})
|
||||
|
||||
local placeId = MockId()
|
||||
local returnedPlaceInfo = ReceivedMultiplePlaceInfos({
|
||||
{
|
||||
placeId = placeId,
|
||||
imageToken = "image-token",
|
||||
},
|
||||
})
|
||||
|
||||
state = PlaceInfosReducer(state, returnedPlaceInfo)
|
||||
|
||||
expect(state[placeId]).to.equal(returnedPlaceInfo.placeInfos[1])
|
||||
end)
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
local TimeUnit = setmetatable({}, {
|
||||
__index = function(self, key)
|
||||
error(("Invalid TimeUnit \"%s\""):format(tostring(key)), 2)
|
||||
end
|
||||
})
|
||||
|
||||
TimeUnit.Seconds = "Seconds"
|
||||
TimeUnit.Minutes = "Minutes"
|
||||
TimeUnit.Hours = "Hours"
|
||||
TimeUnit.Days = "Days"
|
||||
TimeUnit.Months = "Months"
|
||||
TimeUnit.Years = "Years"
|
||||
|
||||
-- Locale-specific
|
||||
TimeUnit.Weeks = "Weeks"
|
||||
|
||||
return TimeUnit
|
||||
@@ -0,0 +1,10 @@
|
||||
local TimeZone = setmetatable({}, {
|
||||
__index = function(self, key)
|
||||
error(("Invalid TimeZone \"%s\""):format(tostring(key)), 2)
|
||||
end
|
||||
})
|
||||
|
||||
TimeZone.UTC = -2
|
||||
TimeZone.Current = -1
|
||||
|
||||
return TimeZone
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"language": {
|
||||
"mode": "nonstrict"
|
||||
},
|
||||
"lint": {
|
||||
"ImplicitReturn": "fatal"
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
|
||||
local User = require(CorePackages.AppTempCommon.LuaApp.Models.User)
|
||||
local WebPresenceMap = require(CorePackages.AppTempCommon.LuaApp.Enum.WebPresenceMap)
|
||||
local convertUniverseIdToString = require(CorePackages.AppTempCommon.LuaApp.Flags.ConvertUniverseIdToString)
|
||||
|
||||
return function(friendsPresence, store)
|
||||
local placeIds = {}
|
||||
|
||||
for _, presenceModel in pairs(friendsPresence) do
|
||||
local universeId = convertUniverseIdToString(presenceModel.universeId)
|
||||
if WebPresenceMap[presenceModel.userPresenceType] == User.PresenceType.IN_GAME
|
||||
and (not store:getState().UniversePlaceInfos[universeId]) then
|
||||
table.insert(placeIds, presenceModel.placeId)
|
||||
end
|
||||
end
|
||||
|
||||
return placeIds
|
||||
end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
local CorePackages = game:GetService("CorePackages")
|
||||
|
||||
local ReceivedUserPresence = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedUserPresence)
|
||||
local WebPresenceMap = require(CorePackages.AppTempCommon.LuaApp.Enum.WebPresenceMap)
|
||||
|
||||
local FFlagLuaAppConvertUniverseIdToString = settings():GetFFlag("LuaAppConvertUniverseIdToStringV364")
|
||||
|
||||
return function(friendsPresence, store)
|
||||
for _, presenceModel in pairs(friendsPresence) do
|
||||
local userInStore = store:getState().Users[tostring(presenceModel.userId)]
|
||||
local previousUniverseId = userInStore and userInStore.universeId or nil
|
||||
|
||||
local universeId
|
||||
if FFlagLuaAppConvertUniverseIdToString then
|
||||
universeId = presenceModel.universeId and tostring(presenceModel.universeId) or nil
|
||||
else
|
||||
universeId = presenceModel.universeId
|
||||
end
|
||||
|
||||
store:dispatch(ReceivedUserPresence(
|
||||
tostring(presenceModel.userId),
|
||||
WebPresenceMap[presenceModel.userPresenceType],
|
||||
presenceModel.lastLocation,
|
||||
presenceModel.placeId and tostring(presenceModel.placeId) or nil,
|
||||
presenceModel.rootPlaceId and tostring(presenceModel.rootPlaceId) or nil,
|
||||
presenceModel.gameId and tostring(presenceModel.gameId) or nil,
|
||||
presenceModel.lastOnline and tostring(presenceModel.lastOnline) or nil,
|
||||
universeId,
|
||||
previousUniverseId
|
||||
))
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user