Module:TwitterSnowflake/sandbox
See also the companion subpage for test cases (run).
| Related pages |
|---|
This is a Lua module to translate snowflakes from platforms such as Twitter and Discord to timestamps. This can be used for automatically generating dates for templates like {{cite tweet }}.
Usage
[edit ]There is one required parameter: |id_str=, which must be the snowflake ID of the tweet. For example, 1345021162959503360.
{{#invoke:TwitterSnowflake|snowflakeToDate|id_str=1345021162959503360}} returns January 1, 2021.
To specify the date format, use |format=.
{{#invoke:TwitterSnowflake|snowflakeToDate|id_str=1345021162959503360|format=%e %B %Y}} returns 1 January 2021 — useful to specify, especially for use in CS1 citations, in case the default date format would change in the future (though unlikely).
Custom epoch
[edit ]By default, the epoch used is that of Twitter. To specify a different epoch, such as that of Twitter, use |epoch=. The epoch of Discord is 1420070400
{{#invoke:TwitterSnowflake|snowflakeToDate|id_str=797545051047460888|epoch=1420070400}} returns January 9, 2021.
See also
[edit ]Editors can experiment in this module's sandbox (edit | diff) and testcases (edit | run) pages.
Add categories to the /doc subpage. Subpages of this module.
localp={} localDate=require('Module:Date')._Date functionp.snowflakeToDate(frame) localformat=frame.args.formator"%B %e, %Y" localepoch=tonumber(frame.args.epoch)or1288834974 localid_str=frame.args.id_str iftype(id_str)~="string"thenerror("bad argument #1 (expected string, got "..type(id_str)..")",2)end iftype(format)~="string"thenerror("bad argument #2 (expected string, got "..type(format)..")",2)end iftype(epoch)~="number"thenerror("bad argument #3 (expected number, got "..type(epoch)..")",2)end localhi,lo=0,0 localhiexp=1 localtwo32=2^32 forcinid_str:gmatch(".")do lo=lo*10+c iflo>=two32then hi,lo=hi*10^hiexp+math.floor(lo/two32),lo%two32 hiexp=1 elsehiexp=hiexp+1end end hi=hi*10^(hiexp-1) localtimestamp=math.floor((hi*1024+math.floor(lo/4194304))/1000)+epoch returnos.date(format,timestamp) end functionp.getDate(frame) -- just pass frame directly to snowflakeToDate, this wraps it but the args are the same plus if(frame.args.id_str):match("%D")then-- not a number, so return -2 return-2 end frame.args.format="%B %e, %Y" ifframe.args.datethen frame.args.date=mw.ustring.gsub(frame.args.date,"(%d%d%d%d)%a","%1") end frame.args.epoch=tonumber(frame.args.epoch)or1288834974 localepochdate=Date(os.date("%B %e, %Y",frame.args.epoch)) localtwitterdate=Date(p.snowflakeToDate(frame)) iftwitterdate==epochdatethen-- created before epoch, so can't determine the date return-1 end localdate=Date(frame.args.date)or0-- if we error here, then an input of no date causes an error, which is contrary to the entire way {{TwitterSnowflake/datecheck}} works returndate-twitterdate end localfunctionabs_datediff(x) iftype(x)=='number'thenreturnmath.abs(x)end returnmath.abs(x.age_days) end functionp.datecheck(frame) localargs=frame.args ifnot(args.dateandargs.id_str)then error('Must define date and id_str, even if they are blank.') end localerrors={ args.error1or'Date mismatch of two or more days', args.error2or'No date, and posted before November 4, 2010', args.error3or'Invalid id_str' } ifmw.title.getCurrentTitle():inNamespace(0)andargs.error_catthen fori=1,3doerrors[i]=errors[i]..'[['..args.error_cat..']]'end end ifnotargs.date:match('^%s*$')then-- #if:{{{date|}}} localtestResult=p.getDate{args={date=args.date,id_str=args.id_str}} iftestResult==-2thenreturnerrors[3]end ifabs_datediff(testResult)>1thenreturnerrors[1]end elseifnotargs.id_str:match('^%s*$')then localtestResult=p.getDate{args={id_str=args.id_str}} iftestResult==-1thenreturnerrors[2]end iftestResult==-2thenreturnerrors[3]end end end returnp