local CorePackages = game:GetService("CorePackages") local GetFFlagUseDateTimeType = require(CorePackages.AppTempCommon.LuaApp.Flags.GetFFlagUseDateTimeType) 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") expect(format("A")).to.equal("PM") expect(format("a")).to.equal("pm") 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 expect(date:Format("a", TimeZone.UTC)).to.equal("am") 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 expect(date:Format("a", TimeZone.UTC)).to.equal("pm") 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 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", } 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) expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM") 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) expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Sun | 1:00 PM") 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) expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20 | 1:00 PM") 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) expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010 | 1:00 PM") 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) expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM") 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) expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Sun") 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) expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20") 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) expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010") 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