本网站正在建设中(~ ̄▽ ̄)~

  • 你好~!欢迎来到中文歌声合成个人收集站-VCPedia.cn!
  • 若发现页面信息有误投稿至本站,请联系管理员。

Module:模糊时间

VCPedia.cn ——关于中文歌声合成的一切。
跳到导航 跳到搜索

模糊时间模块用于匹配获取一个时间文本,进而,可以进行时间计算、时间比较、时区调整、依据给定的格式进行格式化。 与其他时间函数不同之处在于,本模块支持不规范的、模糊描述以及时间段描述的文本,并允许在格式化时省略精确度不足的内容。

函数

initialize(from,to,connect)

初始化设置。

  • from为文本语言,可选zh/en/all,默认为zh
  • to为格式化目标语言,可选zh/en,默认为zh
  • connect为时间连接符,指格式化时使用时间段概念时连接两时间点的文本。默认为

toTime(text,analysis_pattern)

将文本解析转换为time表time表具有os.time可以识别的结构。

  • 能识别ISO 8601格式的时间,如2025-06-15T15:01:17+00:00。但暂不识别追加的时区文本。
  • 能识别带有单位的文本,如2012年。支持乱序。
  • 能识别特定的时间描述,如星期五凌晨
  • 字符-\被视为时间段的描述关键字。
  • 字符%s中文空格,被忽略。

基本可以认为,所有该函数可以输出的格式化格式,都可以被其识别。

如果指定analysis_pattern,则将使用固定的格式进行匹配。对于固定格式的文本,将大大节省解析时间。其中格式匹配符与#占位符标准相同。没有指定该参数的场合,函数将试图使用所有可能的格式进行分析匹配。

time表的属性

yearmonthdayweekwdayydayhourminutesecond

time表的函数

time表可以执行以下函数:

运算符
time:__connect(other)

..。连接两时间,获得时间段。

time:__add(other)

+。时间加法。

time:__sub(other)

-。时间减法。

其他函数
time:add(tag,value)

按标签计算。标签可以为属性其一。暂且唯有原time中具有该精确度的标签才有效。

time:convert(o_timezone,c_timezone)

时区转换。 c_timezone默认为当前时区。o_timezone默认为{{TimeZone}}所定义的时区。

time:supply(other,pre,after)

补足精确度。使用另一时间对其补足缺失的精确度以及值。已有部分则忽略。 pre为true则补足前部缺失值(如年、月),after设置为true则补足后部缺失值(如秒、分)。两参数默认为true。

time:getNumber()

获取时间段前后的对应os.time数值。

time:sort()

规范数据,计算后如果需要从属性获得准确值需调用。在格式化前会自动调用。

time:format(pattern,ignore)

格式化为文本。 ignore如果为true,则在非必要时忽略区域性描述(诸如旬)(如果精确度只达到该描述,则不省略)。如果为false,则强制要求所有精确度都输出值。ignore默认为nil,此时正常输出,忽略不具备的精确度。

其中pattern的占位符标准详见#占位符

format(text,pattern,ignore,o_timezone,c_timezone,a_pattern)

格式化输出。这个函数是功能的集合版本。

  • text为时间文本
  • ignore同上。
  • pattern的占位符标准详见#格式化
  • o_timezone原时区,即文本使用时区
  • c_timezone现时区,即显示时区。默认采用{{timezone}}模板定义的时区。
  • a_pattern,分析用字符串。

格式化

格式化使用作为时间段描述方式(或许可以考虑增加到占位符中)。 格式化使用的替换用占位符如下。 待扩展中文数字表达。 Lua错误 在package.lua的第80行:module 'Module:queue' not found 示例时间:Template:模糊时间


类型 格式化参数 说明 输出

  1. local module = {}
  2. local getArgs = require('Module:Arguments').getArgs
  3. --本模块用于解析任意时间文本,并选择任意的格式化形式。
  4. --要注意,时间文本并非一种精确的数值,而是包含着模糊性、连续性的描述。
  5. --初步将模糊理解为单位层级。
  6. --要将时间文本的模糊记录下来。如果没有格式化要求,那么应当保留这种模糊性。
  7. --格式化的要求允许指定某主要单位下显示/不显示,指定主要单位的首选、必选显示单位,指定次序。允许更改时区、进行计算。
  8. --正常的格式化要求下不应该改变信息含量
  9. --一个合法的时间必须有确定的c模糊度,确切的说应当是一个连续无中断信息。
  10. --支持ISO 8601
  11. --辅助处理
  12. function string.findAny(text,patterns,index)
  13. index=index or 1
  14. for _,pattern in ipairs(patterns) do
  15. local b,e=text:find(pattern,index)
  16. if b then
  17. return b,e
  18. end
  19. end
  20. return false
  21. end
  22. local FormatString = {}
  23. function string.buildTrie(formats)
  24. root = {}
  25. root.next = {}
  26. for _, format in ipairs(formats) do
  27. for i, item in ipairs(format) do
  28. if item.format then
  29. local cur = root
  30. for i = 1, mw.ustring.len(item.format), 1 do
  31. local c = mw.ustring.sub(item.format, i, i)
  32. if cur.next[c] == nil then
  33. cur.next[c] = {} -- new node
  34. cur.next[c].next = {}
  35. cur.next[c].father = cur
  36. cur.next[c].char = c
  37. end
  38. cur = cur.next[c]
  39. end
  40. cur.item = item
  41. cur.len = mw.ustring.len(item.format)
  42. end
  43. end
  44. end
  45. root.fail = {}
  46. local q = require("Module:queue")
  47. q:push(root)
  48. while not(q:empty()) do
  49. local cur = q:front()
  50. q:pop()
  51. for i, t in pairs(cur.next or {}) do
  52. q:push(t)
  53. end
  54. if (cur ~= root) and (cur.father ~= root) then
  55. cur2 = cur.father
  56. while cur2.fail.next[cur.char] ~= nil and cur2 ~= root do
  57. cur2 = cur2.fail
  58. end
  59. cur.fail = cur2.fail.next[cur.char] or root
  60. else
  61. cur.fail = root
  62. end
  63. end
  64. return root
  65. end
  66. function string.replaceTrie(str, trie, extras)--用数据格式化文本
  67. local cur_state = trie
  68. local i = 1
  69. --local matched_times = 0
  70. while i <= mw.ustring.len(str) do
  71. local c = mw.ustring.sub(str, i, i)
  72. while cur_state.next[c] == nil and cur_state ~= trie do
  73. cur_state = cur_state.fail or trie
  74. end
  75. cur_state = cur_state.next[c] or trie
  76. if cur_state.item ~= nil then
  77. --matched_times = matched_times + 1matched_times,
  78. local newStr = cur_state.item:callback(extras)
  79. -- mw.log(mw.ustring.sub(str, i - cur_state.len + 1, i)..' -> '..newStr)
  80. str = mw.ustring.sub(str, 1, i - cur_state.len)..newStr..mw.ustring.sub(str, i + 1, mw.ustring.len(str))
  81. i = i + mw.ustring.len(newStr) - cur_state.len
  82. cur_state = trie
  83. end
  84. i = i + 1
  85. end
  86. return str
  87. end
  88. function string.matchTrie(str, trie,text,extras)--用文本获取数据
  89. local cur_state = trie
  90. local index=1
  91. local i = 1
  92. --local matched_times = 0
  93. while i <= mw.ustring.len(str) do
  94. local c = mw.ustring.sub(str, i, i)
  95. while cur_state.next[c] == nil and cur_state ~= trie do
  96. cur_state = cur_state.fail or trie
  97. end
  98. cur_state = cur_state.next[c] or trie
  99. if cur_state.item ~= nil then
  100. --matched_times = matched_times + 1
  101. index = cur_state.item:matchback(extras,text,index)
  102. if index>#text then
  103. return index
  104. end
  105. -- mw.log(mw.ustring.sub(str, i - cur_state.len + 1, i)..' -> '..newStr)
  106. cur_state = trie
  107. end
  108. i = i + 1
  109. end
  110. return index
  111. end
  112. --时间单位。
  113. --时间单位将指示时间段限定的范畴。
  114. --时间单位皆有name,range属性,analysis、format函数
  115. --时间单位需要能够从时间文本、时间段中提取值,也能赋值到这两者之中。
  116. --时间单位有着占用组别,它们有着优先度,占用同一数值。如上旬与三月占用同一组。每一组只能有一个单位适用。
  117. --解析器是固定的,但格式化是可变的。
  118. local timeUnit={name="nil",_min=1,_max=math.huge,_priority=0,_begin=0}
  119. --构建函数--
  120. function timeUnit.base(tag,priority)--基础单位。
  121. local unit={
  122. tag=tag,
  123. _priority=priority,
  124. }
  125. return setmetatable(unit,timeUnit)
  126. end
  127. timeUnit.__index = timeUnit
  128. function timeUnit:setName(text)--设置标签文本,仅用于调试
  129. self.name=text
  130. return self
  131. end
  132. function timeUnit:pattern(patternAnalysis,patternFormat)--设置模式字符串
  133. self.patternAnalysis=patternAnalysis or self.patternAnalysis
  134. self.patternFormat=patternFormat or self.patternFormat
  135. return self
  136. end
  137. function timeUnit:fill(number)--指示格式输出数字的必须位数
  138. self.patternFormat="%0"..number.."d"
  139. return self
  140. end
  141. function timeUnit:patternFixed(pattern)--纯粹形式
  142. self.patternAnalysis=pattern
  143. self.patternFormat=pattern
  144. return self
  145. end
  146. function timeUnit:patternPrefix(name)--前缀形式
  147. self.patternAnalysis=name.."^(%d+)"
  148. self.patternFormat=name.."%d"
  149. return self
  150. end
  151. function timeUnit:patternSuffix(name)--后缀形式
  152. self.patternAnalysis="^(%d+)"..name
  153. self.patternFormat="%d"..name
  154. return self
  155. end--可以考虑中文数字支持
  156. function timeUnit:priority(number)--设置优先度
  157. self._priority=number
  158. return self
  159. end
  160. function timeUnit:__lt(other)--排序使用
  161. return self._priority<other._priority
  162. end
  163. function timeUnit:b(number)--设置最小精度开始于,即对于区块开始于
  164. self._begin=number
  165. return self
  166. end
  167. function timeUnit:_convertTo(value)--到time时的值转换
  168. return value
  169. end
  170. function timeUnit:_convertFrom(value)--到字面时的值转换
  171. return value
  172. end
  173. function timeUnit:ratio(number)--设置倍率
  174. local convertTo=self._convertTo
  175. self._convertTo=function(value)
  176. return convertTo(value)*number
  177. end
  178. local convertFrom=self._convertFrom
  179. self._convertFrom=function(value)
  180. return convertFrom(value/number)
  181. end
  182. return self
  183. end
  184. function timeUnit:move(number)--设置值位移,即特殊情况下单位与实际值的差异(用于世纪)
  185. local convertTo=self._convertTo
  186. self._convertTo=function(value)
  187. return convertTo(value)+number
  188. end
  189. local convertFrom=self._convertFrom
  190. self._convertFrom=function(value)
  191. return convertFrom(value-number)
  192. end
  193. return self
  194. end
  195. function timeUnit:accuracy(min,max)--设置精度
  196. self._min=min
  197. self._max=max
  198. return self
  199. end
  200. function timeUnit:des(text)
  201. self.description=text
  202. return self
  203. end
  204. function timeUnit:formatFuc(fuc)--设置格式化函数
  205. self.formatText=fuc
  206. return self
  207. end
  208. function timeUnit:na()--指示不用于分析
  209. self._na=true
  210. return self
  211. end
  212. function timeUnit:f(pattern)--指示使用本unit格式化的指示符
  213. self.format=pattern
  214. return self
  215. end
  216. --延展构建--基于本单位的单位
  217. function timeUnit:append()
  218. self.__index = self
  219. return setmetatable({},self)
  220. end
  221. function timeUnit:appendNumber(number)
  222. local unit=self:append()
  223. unit.patternAnalysis="^(%d+)"
  224. unit.patternFormat="%d"
  225. return unit
  226. end
  227. function timeUnit:appendPrefix(text)
  228. local unit=self:append()
  229. unit:patternPrefix(text)
  230. return unit
  231. end
  232. function timeUnit:appendSuffix(text)
  233. local unit=self:append()
  234. unit:patternSuffix(text)
  235. return unit
  236. end
  237. --功能函数
  238. function timeUnit:available()--指示不用于分析
  239. return not self._na
  240. end
  241. function timeUnit:priorityCompare(other)--判断优先低于
  242. return self._priority<other._priority
  243. end
  244. function timeUnit:analysis(time,text,index)--从文字解析
  245. local value=text:match(self.patternAnalysis,index)
  246. if value then
  247. --assert(type(value)=="number",self.patternAnalysis..";"..text)
  248. _,index=text:find(self.patternAnalysis,index)--可以优化?
  249. index=index+1
  250. --time.units:push({self,value})
  251. return value,index
  252. end
  253. return nil,index
  254. end
  255. function timeUnit._convertTo(value)--到time时的值转换
  256. return value
  257. end
  258. function timeUnit._convertFrom(value)--到字面时的值转换
  259. return value
  260. end
  261. function timeUnit:supplyTime(time,value)--为time赋值
  262. time:setValue(self.tag,self._convertTo(value),self._min,self._max,self._begin)
  263. end
  264. function timeUnit:matchback(time,text,index) --分析用
  265. local value,index=self:analysis(time,text,index)
  266. if value then
  267. self:supplyTime(time,value)
  268. end
  269. return index
  270. end
  271. function timeUnit:getValue(time)--从time获取值
  272. local value=time:getValue(self.tag,self._min,self._max,self._begin,self._min)
  273. return value and self._convertFrom(value)
  274. end
  275. function timeUnit:formatText(value)--返回格式化文本
  276. return string.format(self.patternFormat,value)
  277. end
  278. function timeUnit:callback( time) --格式化用
  279. local value= self:getValue(time)
  280. if value then
  281. return self:formatText(value)
  282. end
  283. return ""
  284. end
  285. timeUnit.Multi={}--多标签识别
  286. function timeUnit.Multi:analysis(time,text,index)--从文字解析
  287. local value={text:match(self.patternAnalysis,index)}
  288. if value[1] then
  289. _,index=text:find(self.patternAnalysis,index)--可以优化?
  290. --time.units:push({self,value})
  291. return value,index+1
  292. end
  293. return nil,index
  294. end
  295. function timeUnit.Multi:supplyTime(time,value)--为time赋值
  296. for index,unit in ipairs(self.units) do
  297. unit:supplyTime(time,value[index])
  298. end
  299. end
  300. function timeUnit.Multi:formatText(value)--返回格式化文本
  301. return string.format(self.patternFormat,unpack(value))
  302. end
  303. function timeUnit.Multi:getValue(time)
  304. local t={}
  305. for index,unit in ipairs(self.units) do
  306. table.insert(t,unit:getValue(time))
  307. end
  308. return #t==#self.units and t
  309. end
  310. function timeUnit.multi(units)
  311. local unit=timeUnit.base()
  312. unit.units=units
  313. unit._priority=units[#units]._priority
  314. unit.analysis=timeUnit.Multi.analysis
  315. unit.supplyTime=timeUnit.Multi.supplyTime
  316. unit.formatText=timeUnit.Multi.formatText
  317. unit.getValue=timeUnit.Multi.getValue
  318. return unit
  319. end
  320. --[[--识别多个单位的连接
  321. --这样就有点像语言识别系统了..说不定就该用语言识别系统做基础
  322. function timeMultiUnit:analysis(time,text,index)
  323. local i=index
  324. local vt={}
  325. for _,unit in ipairs(self.units) do
  326. local value,i=unit:analysis(time,text,i)
  327. if not value then
  328. return nil,index
  329. end
  330. table.insert(vt,value)
  331. end
  332. return vt,i
  333. end
  334. function timeMultiUnit:supplyTime(time,value)--为time赋值
  335. for index,unit in ipairs(self.units) do
  336. unit:supplyTime(time,value[index])
  337. end
  338. end
  339. function timeMultiUnit:callBack(_, time) --格式化用
  340. local t={}
  341. for index,unit in ipairs(self.units) do
  342. table.insert(t,unit:callBack(_,time))
  343. end
  344. return table.concat(t)
  345. end]]
  346. timeUnit.List={}--文本列表单位,对应正当格式但不用阿拉伯数字描述的单位
  347. function timeUnit.List:analysis(time,text,index)--从文字解析,匹配为time记录
  348. for value,name in pairs(self.names) do
  349. if text:sub(index,index+#name-1)==name then
  350. --mw.log(self.tag,value,index+#name,index)
  351. return value,index+#name
  352. end
  353. end
  354. return nil,index
  355. end
  356. function timeUnit.List:formatText(value)--返回格式化文本
  357. --mw.log(value,self.names[value])
  358. return self.names[value] or ""
  359. end
  360. function timeUnit:appendList(names)--扩展数组形式的单位表
  361. local unit=self:append()
  362. unit.names=names
  363. unit.analysis=timeUnit.List.analysis
  364. unit.formatText=timeUnit.List.formatText
  365. return unit
  366. end
  367. timeUnit.Group={}--文本列表单位,对应正当格式但不用阿拉伯数字描述的单位,并且允许使用不同的区间值
  368. function timeUnit.Group.createIndex(t)
  369. local a = {}
  370. for n in pairs(t) do
  371. a[#a+1] = n
  372. end
  373. table.sort(a)
  374. return a
  375. end
  376. timeUnit.Group.analysis=timeUnit.List.analysis
  377. function timeUnit.Group:formatText(value)--返回格式化文本)
  378. for index,v in ipairs(self.index) do
  379. if v>value then
  380. if self.index[index-1] then
  381. return self.names[self.index[index-1]]
  382. else
  383. return ""
  384. end
  385. end
  386. end
  387. return self.names[self.index[#self.index]] or ""
  388. end
  389. function timeUnit:appendGroup(args)
  390. local unit=self:append()
  391. unit.names=args
  392. unit.index=timeUnit.Group.createIndex(args)
  393. unit.analysis=timeUnit.Group.analysis
  394. unit.formatText=timeUnit.Group.formatText
  395. return unit
  396. end
  397. --时间精度
  398. --精度有两方面,未知的前缀与未知的后缀。
  399. local timeAccuracy={
  400. max=1,--最前精度
  401. maxA=1,
  402. min=7,--最后精度
  403. minA=math.huge,
  404. }
  405. timeAccuracy.baseData={["year"]=7,["month"]=6,["week"]=5,["yday"]=4,["day"]=4,["wday"]=4,["hour"]=3,["min"]=2,["sec"]=1}
  406. timeAccuracy.indexToTag={"sec","min","hour","day","week","month","year"}
  407. function timeAccuracy.create(args)
  408. return setmetatable(args or {},timeAccuracy)
  409. end
  410. timeAccuracy.__index=timeAccuracy
  411. timeAccuracy.clear=timeAccuracy.create{max=1,maxA=math.huge,min=7,minA=1}
  412. function timeAccuracy.lt(l,la,r,ra)--小于
  413. return l<r or (l==r and la<ra)
  414. end
  415. function timeAccuracy.le(l,la,r,ra)--小于等于
  416. return l<r or (l==r and la<=ra)
  417. end
  418. function timeAccuracy:setMin(min,minA)
  419. self.min=min
  420. self.minA=minA
  421. end
  422. function timeAccuracy:setMax(max,maxA)
  423. self.max=max
  424. self.maxA=maxA
  425. end
  426. function timeAccuracy:isNull()
  427. return timeAccuracy.le(self.max,self.maxA,self.min,self.minA)
  428. end
  429. function timeAccuracy:limit(tag,min,max)--限制、精确范围
  430. local index=timeAccuracy.baseData[tag]
  431. max=max or min
  432. if timeAccuracy.lt(self.max,self.maxA,index,max) then
  433. self:setMax(index,max)
  434. end
  435. if timeAccuracy.lt(index,min,self.min,self.minA) then
  436. self:setMin(index,min)
  437. end--两者间的空间为已知精确
  438. end
  439. function timeAccuracy:_cover(index,value,direct)--遮盖、模糊范围
  440. if direct then--true为遮蔽右侧
  441. if timeAccuracy.lt(self.min,self.minA,index,value) then
  442. if value==math.huge then--进位
  443. self:setMin(index+1,1)
  444. else
  445. self:setMin(index,value)
  446. end
  447. end
  448. else
  449. if timeAccuracy.lt(index,value,self.max,self.maxA) then
  450. if value==1 then--进位
  451. self:setMax(index-1,math.huge)
  452. else
  453. self:setMax(index,value)
  454. end
  455. end
  456. end
  457. end
  458. function timeAccuracy:cover(tag,value,direct)--遮盖、模糊范围
  459. local index=timeAccuracy.baseData[tag]
  460. self:_cover(index,value,direct)
  461. end
  462. function timeAccuracy:coverBy(other,direct)--遮盖、模糊范围
  463. if direct then--true为遮蔽右侧
  464. self:_cover(other.max,other.maxA,direct)
  465. else
  466. self:_cover(other.min,other.minA,direct)
  467. end
  468. end
  469. function timeAccuracy:loverThan(tag,min,max)--是否比指定标签下的精度更低--即数据是否没有涵盖该精度
  470. local index=timeAccuracy.baseData[tag]
  471. max=max or min
  472. return timeAccuracy.lt(self.max,self.maxA,index,max) or timeAccuracy.lt(index,min,self.min,self.minA)
  473. end
  474. function timeAccuracy:getTagAccuracy(tag)--获取tag下精度,两个数。必须是范围包含的标签
  475. local index=timeAccuracy.baseData[tag]
  476. if self.max<index or index<self.min then
  477. return
  478. end
  479. local first=self.max==index and self.maxA or math.huge
  480. local last=self.min==index and self.minA or 1
  481. return first,last
  482. end
  483. function timeAccuracy:contains(tag,accuracy)--包含精度
  484. return not self:loverThan(tag,accuracy)
  485. end
  486. function timeAccuracy:getMax()--获取最前精度
  487. return timeAccuracy.indexToTag[self.max],self.maxA
  488. end
  489. function timeAccuracy:getMin()--获取最后精度
  490. return timeAccuracy.indexToTag[self.min],self.minA,self.begin
  491. end
  492. function timeAccuracy.getTags_step(self,index)
  493. index=index-1
  494. if (index<self.min) then--超过界限
  495. return
  496. end
  497. if index==self.min then
  498. local min=self.minA
  499. end
  500. if index==self.max then
  501. local max=self.maxA
  502. end
  503. return index,timeAccuracy.indexToTag[index],min or 1,max or math.huge
  504. end
  505. function timeAccuracy:getTags()--遍历标签精度,从大到小
  506. return timeAccuracy.getTags_step,self,self.max+1
  507. end
  508. function timeAccuracy.getSupplyPreTags_step(tab,index)
  509. index=index+1
  510. if index>tab[2].max then--超过界限
  511. return
  512. end
  513. if index==tab[2].max then
  514. if index==tab[1].max and tab[1].maxA>=tab[2].maxA then
  515. return
  516. end
  517. return index,timeAccuracy.indexToTag[index],tab[2].maxA
  518. end
  519. return index,timeAccuracy.indexToTag[index],math.huge
  520. end
  521. function timeAccuracy:getSupplyPre(other)--获取other的更高精度的标签、精度 迭代器
  522. return timeAccuracy.getSupplyPreTags_step,{self,other},math.max(self.max,other.min)-1
  523. end
  524. function timeAccuracy.getSupplyAfterTags_step(tab,index)
  525. index=index-1
  526. if (index<tab[2].min) then--超过界限
  527. return
  528. end
  529. if index==tab[2].min then
  530. if index==tab[1].min and tab[1].minA<=tab[2].minA then
  531. return
  532. end
  533. return index,timeAccuracy.indexToTag[index],tab[2].minA
  534. end
  535. return index,timeAccuracy.indexToTag[index],1
  536. end
  537. function timeAccuracy:getSupplyAfter(other)--获取other的更高精度的标签、精度 迭代器
  538. return timeAccuracy.getSupplyAfterTags_step,{self,other},math.min(self.min,other.max)+1
  539. end
  540. --time 时间类
  541. local time={year=1,month=1,week=1,day=1,wday=1,hour=0,min=0,sec=0}
  542. time.zero=os.time(time)
  543. function time.create(args)--设置值
  544. args=args or {}
  545. args.accuracy=timeAccuracy.create()
  546. return setmetatable(args,time)
  547. end
  548. time.__index=time
  549. function time:setEnd(time)--结束时间点
  550. time:supply(self,true,false)
  551. time.accuracy=self.accuracy
  552. self._end=time
  553. end
  554. function time:getAccuracyEnd()--模糊度的范围结束时间点
  555. local tag,range=self.accuracy:getMin()
  556. --mw.log(tag,range)
  557. local e=mw.clone(self)
  558. e[tag]=e[tag]+range
  559. e:update()
  560. return e
  561. end
  562. function time:getEnd()--结束范围并结束模糊度的范围时间点
  563. if not self._accuracy_end then
  564. self._accuracy_end=(self._end or self):getAccuracyEnd()
  565. end
  566. return self._accuracy_end
  567. end
  568. function time.initializeUnit(lang_from,lang_to,connect)--初始化
  569. local base={--单位有优先度--占用同一标签的单位按照优先度予以保留--优先度从低到高都可运算ymd,新的ymd覆盖旧的。
  570. --进行time创建时将优先度从高到低依次调用构建,单位的会因精确已达到而跳过赋值
  571. century =timeUnit.base("year",0) :accuracy(100,math.huge) :b(0):ratio(100):move(-199),
  572. years =timeUnit.base("year",1) :accuracy(10,math.huge) :b(0),
  573. year =timeUnit.base("year",2) :accuracy(1,math.huge) :b(1),
  574. month =timeUnit.base("month",3) :accuracy(1,math.huge) :b(1),
  575. week =timeUnit.base("week",4) :accuracy(1,math.huge) :b(1),
  576. wday =timeUnit.base("wday",5) :accuracy(1,math.huge) :b(1),
  577. yday =timeUnit.base("yday",5.5) :accuracy(1,math.huge):na() :b(1),
  578. day =timeUnit.base("day",6) :accuracy(1,math.huge) :b(1),
  579. mer =timeUnit.base("hour",7) :accuracy(12,math.huge) :b(0):ratio(12),
  580. hour =timeUnit.base("hour",8) :accuracy(1,math.huge) :b(0),
  581. min =timeUnit.base("min",9) :accuracy(1,math.huge) :b(0),
  582. sec =timeUnit.base("sec",10) :accuracy(1,math.huge) :b(0),
  583. --timezone=timeUnit.base("timezone",11),--暂时无意义
  584. }
  585. local standard={--数字-符号格式。应最后分析。
  586. --数字识别。4位将识别为年,3位为日
  587. timeUnit .multi{base.year,base.month,base.day}--ymd
  588. :pattern("^(%d+)\-(%d+)\-(%d+)","%04d\-%02d\-%02d")--正规模式
  589. :des("日期-年月日 (ISO 8601格式)(不支持省略)")
  590. :f("%E"),
  591. timeUnit .multi{base.year,base.month,base.day}--ymd
  592. :pattern("^(%d+)%.(%d+)%.(%d+)","%04d\.%02d\.%02d")--泛用模式
  593. :des("日期-年月日 (ISO 8601格式)(不支持省略)")
  594. :f("%(Eo)"),
  595. timeUnit .multi{base.year,base.month}--ym
  596. :pattern("^(%d%d%d%d+)\-(%d+)"),
  597. timeUnit .multi{base.month,base.day}--md
  598. :pattern("^(%d%d-)\-(%d+)"),
  599. timeUnit .multi{base.year,base.month,base.day}--ymd2
  600. :pattern("^(%d%d%d%d)\-?(%d%d)\-?(%d%d)"),--数字模式
  601. timeUnit .multi{base.year,base.week,base.wday}--ywd
  602. :pattern("^(%d+)\-W(%d+)\-(%d+)","%04d\-W%02d\-%d")--正规模式
  603. :des("日期-年周星期 (ISO 8601格式)(不支持省略)")
  604. :f("%(Ew)"),
  605. timeUnit .multi{base.year,base.week}--yw
  606. :pattern("^(%d%d%d%d+)\-?W(%d%d-)"),
  607. timeUnit .multi{base.week,base.wday}--wd
  608. :pattern("^W(%d%d-)\-?(%d)"),
  609. timeUnit .multi{base.year,base.week,base.wday}--ywd2
  610. :pattern("^(%d%d%d%d)\-?W(%d%d)\-?(%d)"),--数字模式
  611. timeUnit .multi{base.hour,base.min,base.sec}--his
  612. :pattern("^(%d+)\:(%d+)\:(%d+)","%02d\:%02d\:%02d")--正规模式
  613. :des("时间-时分秒 (ISO 8601格式)(不支持省略)")
  614. :f("%e"),
  615. timeUnit .multi{base.hour,base.min}:setName("--hi")
  616. :pattern("^(%d+)\:(%d+)"),--可能需要扩展
  617. timeUnit .multi{base.hour,base.min,base.sec}--his2
  618. :pattern("^T(%d%d)\:?(%d%d)\:?(%d%d)"),
  619. base.year :appendNumber()--四位纯数字--yearF
  620. :pattern("^(%d%d%d%d)"),
  621. base.mer :appendList{[0]="am","pm"}--mer
  622. :des("根据时间是上午还是下午,输出am或pm")
  623. :f("%a"),
  624. base.mer :appendList{[0]="AM","PM"}--meridiem
  625. :des("根据时间是上午还是下午,输出AM或PM")
  626. :f("%(au)"),
  627. timeUnit .multi{base.hour,base.min}--timezone
  628. :priority(11)
  629. :pattern("^([-%+]%d+):?(%d+)")
  630. :des("时区"),--:f("%(au)")
  631. }
  632. local expend={--只用于格式化
  633. base.century:appendNumber()--centuryF
  634. :pattern("^(%d%d)")
  635. :des("日期-世纪,2位数字,补足前导0")
  636. :fill(2)
  637. :f("%(cf)"),
  638. base.years :appendNumber()--yearsF
  639. :pattern("^(%d%d)")
  640. :des("日期-年代,2位数字,补足前导0")
  641. :fill(2)
  642. :accuracy(10,100)
  643. :f("%(tf)"),
  644. base.year :appendNumber()--四位纯数字--yearF
  645. :pattern("^(%d%d%d%d)")
  646. :fill(4)
  647. :des("日期-年份,4位数字,补足前导0")
  648. :f("%(yf)"),
  649. base.month :appendNumber()--monthF
  650. :pattern("^(%d%d)")
  651. :des("日期-月,2位数字,补足前导0")
  652. :fill(2)
  653. :f("%(mf)"),
  654. base.day :appendNumber()--dayF
  655. :pattern("^(%d%d)")
  656. :des("日期-日,2位数字,补足前导0")
  657. :fill(2)
  658. :f("%(df)"),
  659. base.week :appendNumber()--获得的W开头两位数字识别为周--weekF
  660. :pattern("^W(%d%d)")
  661. :des("日期-年内第几周,2位数字,补足前导0")
  662. :fill(2)
  663. :f("%(wf)"),
  664. base.hour :appendNumber()--hourF
  665. :pattern("^(%d%d)")
  666. :des("时间-小时,2位数字,补足前导0")
  667. :fill(2)
  668. :f("%(hf)"),
  669. base.min :appendNumber()--minF
  670. :pattern("^(%d%d)")
  671. :des("时间-分钟,2位数字,补足前导0")
  672. :fill(2)
  673. :f("%(if)"),
  674. base.sec :appendNumber()--secF
  675. :pattern("^(%d%d)")
  676. :des("时间-秒,2位数字,补足前导0")
  677. :fill(2)
  678. :f("%(sf)"),
  679. base.century:appendNumber()--century
  680. :des("日期-世纪")
  681. :f("%c"),
  682. base.years :appendNumber()--years
  683. :des("日期-年代")
  684. :f("%t"),
  685. base.year :appendNumber()--year
  686. :des("日期-年份")
  687. :f("%y"),
  688. base.month :appendNumber()--month
  689. :des("日期-月")
  690. :f("%m"),
  691. base.week :appendNumber()--week
  692. :des("日期-年内第几周")
  693. :f("%w"),
  694. base.day :appendNumber()--day
  695. :des("日期-日")
  696. :f("%d"),
  697. base.yday :appendNumber()--yday
  698. :des("日期-日 年内第几日")
  699. :f("%(dy)"),
  700. base.wday :appendNumber()--已有周,获得的一位数字识别为星期--wday
  701. :pattern("^(%d)")
  702. :des("日期-星期,1位数字")
  703. :f("%l"),
  704. base.hour :appendNumber()--hour
  705. :des("时间-小时")
  706. :f("%h"),
  707. base.hour :appendNumber()--hour
  708. :des("时间-小时 十二小时制")
  709. :accuracy(1,12)
  710. :b(0)
  711. :f("%(hy)"),
  712. base.min :appendNumber()--min
  713. :des("时间-分钟")
  714. :f("%i"),
  715. base.sec :appendNumber()--sec
  716. :des("时间-秒")
  717. :f("%s"),
  718. timeUnit .multi{base.year,base.month,base.day,base.hour,base.min,base.sec}--ios
  719. :pattern("^%d%d%d%d-?%d%d-%d%d T%%d%d:?%d%d:?%d%d","%04d-%02d-%02d T%02d:%02d:%02d")
  720. :des("年月日时分秒 (ISO 8601格式)(不支持省略)")
  721. :f("%X"),
  722. timeUnit .multi{base.year,base.week,base.day,base.hour,base.min,base.sec}--ios2
  723. :pattern("%d%d%d%d-?W%d%d-?%d%d T%%d%d:?%d%d:?%d%d","%04dW%02d-%d T%02d:%02d:%02d")
  724. :des("年周日时分秒 (ISO 8601格式)(不支持省略)")
  725. :f("%x"),
  726. }
  727. local lang={}
  728. lang.en={--英语格式
  729. base.years :appendSuffix("s")--years
  730. :accuracy(10,math.huge)
  731. :f("%T"),
  732. base.month :appendList{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}--monthShort
  733. :f("%(Ms)"),
  734. base.month :appendList{"January","February","March","April","May","June","July","August","September","October","November","December"}
  735. :f("%M"),--month =
  736. base.wday :appendList{"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}--wdayShort
  737. :f("%(Ls)"),
  738. base.wday :appendList{"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}--wday
  739. :f("%L"),
  740. base.day :appendSuffix("nd")--day
  741. :formatFuc(
  742. function(self,value)
  743. return value==1 and value.."st" or value.."nd"
  744. end)
  745. :f("%D"),
  746. base.day :appendSuffix("st"),--day2
  747. }
  748. lang.zh={--中文格式
  749. base.century:appendSuffix("世纪")--century
  750. :des("日期-世纪 单位“世纪”")
  751. :f("%C"),
  752. base.years :appendSuffix("年代")--yearsF
  753. :pattern("^%d%d年代")
  754. :des("日期-年代 单位“年代”,只取后两位")
  755. :accuracy(10,100)
  756. :f("%(Tf)"),
  757. base.years :appendSuffix("年代")--years
  758. :des("日期-年代 单位“年代”")
  759. :accuracy(10,math.huge)
  760. :f("%T"),
  761. base.year :appendSuffix("年")--year
  762. :des("日期-年 单位“年”")
  763. :f("%Y"),
  764. base.month :appendSuffix("月")--month
  765. :des("日期-月 单位“月”")
  766. :f("%M"),
  767. base.month :appendList{"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"}
  768. :des("日期-月 中文文字")--monthC
  769. :f("%(Mc)"),
  770. base.week :appendSuffix("周")--weekN =
  771. :pattern("^第d%+周","第d%周"),
  772. base.week :appendSuffix("周")--week
  773. :des("日期-周 单位“周”")
  774. :f("%W"),
  775. base.day :appendSuffix("日")--day
  776. :des("日期-日 单位“日”")
  777. :f("%D"),
  778. base.yday :appendSuffix("日")--yday
  779. :des("日期-日 年内第几日 单位“日”")
  780. :na()
  781. :f("%(Dy)"),
  782. base.day :appendSuffix("号")--dayO
  783. :des("日期-日 单位“号”")
  784. :f("%(Do)"),
  785. base.wday :appendList{"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}--wday
  786. :des("日期-星期 中文文字“星期”")
  787. :f("%L"),
  788. base.wday :appendList{"周一","周二","周三","周四","周五","周六","周日"}--wdaySS
  789. :des("日期-星期 中文文字大写“周”")
  790. :f("%(Lss)"),
  791. base.wday :appendList{"一","二","三","四","五","六","日"}--wdayS
  792. :des("日期-星期 只输出一个中文文字")
  793. :f("%(Ls)"),
  794. base.hour :appendSuffix("时")--hour
  795. :des("时间-时 单位“时”")
  796. :f("%H"),
  797. base.hour :appendSuffix("时")--hour
  798. :des("时间-时 单位“时” 十二小时制")
  799. :accuracy(1,12)
  800. :na()
  801. :f("%(Hy)"),
  802. base.hour :appendSuffix("点")--hourO
  803. :des("时间-时 单位“点”")
  804. :f("%(Ho)"),
  805. base.min :appendSuffix("分")--min
  806. :des("时间-分 单位“分”")
  807. :f("%I"),
  808. base.sec :appendSuffix("秒")--sec
  809. :des("时间-秒 单位“秒”")
  810. :f("%S"),
  811. --wday =base.week :appendSuffix("星期","^星期d%+","星期d%"),
  812. --shortMonth =base.month:appendList("一","二","三","四","五","六","七","八","九","十","十一","十二"),
  813. base.day :appendGroup{
  814. [1]="上旬",[11]="中旬",[21]="下旬"
  815. } :priority(3.5)--tendays
  816. :accuracy(10,math.huge)
  817. :b(1)
  818. :des("日期-月内描述“旬”,十日为一旬")
  819. :f("%(Mi)"),
  820. base.mer :appendList{[0]="上午","下午"}--mer
  821. :des("时间-根据时间输出上午或下午")
  822. :f("%A"),
  823. base.hour :appendGroup{
  824. [0]="凌晨",[7]="上午",[11]="中午",[13]="下午",[17]="傍晚",[19]="晚上",[22]="深夜"--有争议
  825. } :priority(7.5)--inday =
  826. :des("时间-日内详细描述")
  827. :f("%(Di)"),
  828. }
  829. local filter=function(tab)
  830. local t={}
  831. for _,unit in ipairs(tab) do
  832. if unit:available() then
  833. table.insert(t,unit)
  834. end
  835. end
  836. return t
  837. end
  838. time.analysisTable={}--分析表--本来是可以写成语言,树状分析,但是暂且看来并没有必要。为了兼容更多模糊写法。
  839. if lang_from=="all" then
  840. for _,l in pairs(lang) do
  841. table.insert(time.analysisTable,filter(l))
  842. end
  843. else--lang=="zh"
  844. table.insert(time.analysisTable,filter(lang[lang_from or "zh"]))
  845. end
  846. table.insert(time.analysisTable,filter(standard))
  847. time.analysisConnect={--时间连接符,间隔两时间点
  848. "^到","^至","^\-","^\b","^\\","^、"
  849. }
  850. time.analysisIgnore={--忽略符、间隔符。
  851. "^%s","^ ","^,","^—"
  852. }
  853. time.formatTable={lang[lang_to or "zh"],expend,standard}--格式化表
  854. if connect then
  855. time.formatConnect=connect
  856. else
  857. if lang_to=="en" then
  858. time.formatConnect="-"
  859. else
  860. time.formatConnect="到"
  861. end
  862. end
  863. --追加词,暂未实现--追加在单位后的后缀,可以不断追加。后缀与原单位相关。
  864. local about={
  865. --about =base.hour :appendFixed("左右"),
  866. --about2 =base.hour :appendFixed("前后"),
  867. --about2 =base.hour :appendFixed("约"),
  868. --about2 =base.hour :appendFixed("大概"),
  869. --about2 =base.hour :appendFixed("之间"),
  870. --about2 =base.hour :appendFixed("开始"),
  871. --about2 =base.hour :appendFixed("附近"),
  872. }
  873. time.formatTrie = string.buildTrie(time.formatTable)
  874. return standard,expend,lang
  875. end
  876. --功能函数
  877. function time:isEmpty()--是否为空
  878. return self.accuracy:isNull()
  879. end
  880. function time:_setValue(tag,value,min,max,begin)
  881. --mw.log("set",tag,value,min,max,begin,self:_getValue(tag))
  882. local f,l=self.accuracy:getTagAccuracy(tag)
  883. value=value-begin
  884. --value=math.mod(value,max)-math.mod(value,min)
  885. value=value-math.mod(value,min)
  886. if f then
  887. local valueTag=self[tag]-begin
  888. value=value-math.mod(value,f)+math.mod(value,l)+math.mod(valueTag,f)-math.mod(valueTag,l)--保留值-保留信息已有精度部分内容
  889. --mw.log(tag,min,max,begin,value,value,math.mod(value,f),math.mod(value,l),math.mod(valueTag,f),math.mod(valueTag,l))
  890. end
  891. value=value+begin
  892. self[tag]=value--+math.mod(begin,min)
  893. --mw.log("set","result",tag,self[tag])
  894. end
  895. function time:forceSetValue(tag,value,min,max,begin)--强制设置值--内部函数
  896. self:_setValue(tag,value,min,max,begin)
  897. self.accuracy:limit(tag,min,max)
  898. end
  899. function time:setValue(tag,value,min,max,begin)--设置值--内部函数
  900. if self.accuracy:loverThan(tag,min,max) then
  901. self:forceSetValue(tag,value,min,max,begin or 0)
  902. end
  903. end
  904. function time:_getValue(tag)--实际记录值
  905. local f,l=self.accuracy:getTagAccuracy(tag)
  906. if f then
  907. return self[tag]
  908. end
  909. return time[tag]
  910. end
  911. function time:forceGetValue(tag,min,max,begin)--强制获取值
  912. local value=self[tag]-begin
  913. local f,l=self.accuracy:getTagAccuracy(tag)
  914. if f then
  915. max=math.min(f,max)
  916. min=math.max(l,min)
  917. end
  918. --mw.log("-->",tag,self[tag],max,min,math.mod(value,max)-math.mod(value,min))
  919. return math.mod(value,max)-math.mod(value,min)+begin--+self.accuracy:getTagBegin(tag)
  920. end
  921. function time:getValue(tag,min,max,begin)--获取值
  922. min=min or 1
  923. max=max or math.huge
  924. if self.accuracy:contains(tag,min,max) then
  925. return self:forceGetValue(tag,min,max,begin)
  926. end
  927. end
  928. function time:getValueIgnore(tag,min,max,begin)--获取值--忽略粗略精度版本
  929. min=min or 1
  930. max=max or math.huge
  931. local f,l=self.accuracy:getTagAccuracy(tag)
  932. if f~=max or l~=min then
  933. return nil
  934. end
  935. return self:forceGetValue(tag,min,max,begin)
  936. end
  937. function time:update()--指示需要更新
  938. self.value=nil
  939. self._accuracy_end=nil
  940. self._sorted=false
  941. end
  942. function time:_getNumber()
  943. if not self.value then--改动后清空
  944. local t={}
  945. for _,tag in ipairs(time.keyData) do
  946. t[tag]=self:_getValue(tag) or time[tag]
  947. end
  948. if not rawget(self,"month") and not rawget(self,"day") then--处理周问题
  949. local week=self:_getValue("week")
  950. if week then
  951. local wday=os.date("*t",os.time({year=self.year,month=1,day=1})).wday-1--年内第一天的星期 减去1是因为lua标准中1代表星期日
  952. if wday==0 then wday=7 end--ios标准
  953. t.day= week*7+(wday>4 and 0 or -7)+self.wday-wday+1
  954. end
  955. end
  956. self.value=os.time(t)
  957. end
  958. return self.value
  959. end
  960. function time:getNumber()--获取计算值
  961. return self:_getNumber(),self:getEnd():_getNumber()
  962. end
  963. time.compare={--时间比较结果常数
  964. before=1,--完全在之前
  965. equal=2,--相同
  966. after=3,--完全在之后
  967. include=4,--包含
  968. inside=5,--被包含
  969. conflict=6,--冲突
  970. }
  971. time.compare=setmetatable(time.compare,{--时间比较,理论上只允许发生在同精确度的时间上。
  972. __call=function(self,time1,time2)
  973. local b1,e1=time1:getNumber()
  974. local b2,e2=time2:getNumber()
  975. --mw.log(tostring(time1),tostring(time2))
  976. --mw.log(b1,e1,b2,e2)
  977. if e1<=b2 then return self.before end
  978. if e2<=b1 then return self.after end
  979. if b1==b2 and e1==e2 then return self.equal end
  980. if b1<=b2 then
  981. if e2<=e1 then return self.include end
  982. end
  983. if b2<=b1 then
  984. if e1<=e2 then return self.inside end
  985. end
  986. return self.conflict
  987. end
  988. })
  989. function time:__eq(other)
  990. return self:compare(other)==time.compare.equal
  991. end
  992. function time:__lt(other)
  993. return self:compare(other)==time.compare.before
  994. end
  995. time.keyData={"year","month","day","hour","min","sec"}
  996. time.baseData={"year","month","week","wday","yday","day","wday","hour","min","sec"}
  997. function time:supply(other,pre,after)--利用另一个时间对此时间精确度补足
  998. pre=pre==nil and true or pre
  999. after=after==nil and true or after
  1000. if pre then
  1001. for _,tag,accuracy in self.accuracy:getSupplyPre(other.accuracy) do
  1002. self:_setValue(tag,other:_getValue(tag),1,accuracy,0)
  1003. end
  1004. if self._end then
  1005. for _,tag,accuracy in self.accuracy:getSupplyPre(other.accuracy) do
  1006. self._end:_setValue(tag,other:_getValue(tag),1,accuracy,0)
  1007. end
  1008. end
  1009. self.accuracy:limit(other.accuracy:getMax())
  1010. end
  1011. if after then
  1012. for _,tag,accuracy in self.accuracy:getSupplyAfter(other.accuracy) do
  1013. self:_setValue(tag,other:_getValue(tag),accuracy,math.huge,0)
  1014. end
  1015. if self._end then
  1016. for _,tag,accuracy in self.accuracy:getSupplyAfter(other.accuracy) do
  1017. self._end:_setValue(tag,other:_getValue(tag),accuracy,math.huge,0)
  1018. end
  1019. end
  1020. local tag,min=other.accuracy:getMin()
  1021. self.accuracy:limit(tag,min,min)
  1022. end
  1023. self:update()
  1024. return self
  1025. end
  1026. function time:cover(other,direct)--利用另一个时间对此时间精确度减损遮盖
  1027. --direct指示遮蔽方向,true遮蔽后部精度,false遮蔽前部精度
  1028. self.accuracy:coverBy(other.accuracy,direct)
  1029. self:update()
  1030. return self
  1031. end
  1032. function time:coverRange(other)--遮盖other中到_end前后一致部分单位
  1033. local tag,min
  1034. for _,t,i in other.accuracy:getTags() do
  1035. if other._end and other._end[t]~=other[t] then
  1036. break
  1037. end
  1038. tag=t
  1039. min=i
  1040. end
  1041. if tag then
  1042. self.accuracy:cover(tag,min,false)
  1043. else
  1044. tag,min=other.accuracy:getMax()
  1045. self.accuracy:cover(tag,min,false)
  1046. end
  1047. --mw.log("tag",tag,min)
  1048. self:update()
  1049. return self
  1050. end
  1051. function time:coverUnit(unitTag,direct)--利用unit格式索引unit并以此进行遮盖 也可以认为是截取信息,截取从unit开始的信息--种种问题暂且只支持主要单位
  1052. local unit
  1053. for _,group in ipairs(self.formatTable) do
  1054. for _,u in ipairs(group) do
  1055. if u.format==unitTag then
  1056. unit=u
  1057. break
  1058. end
  1059. end
  1060. end
  1061. if unit then
  1062. --mw.log(self.accuracy.min,self.accuracy.minA,self.accuracy.max,self.accuracy.maxA)
  1063. self.accuracy:cover(unit.tag,direct and unit._min or unit._max,direct)--有点不规范
  1064. --mw.log(self.accuracy.min,self.accuracy.minA,self.accuracy.max,self.accuracy.maxA)
  1065. self:update()
  1066. end
  1067. return self
  1068. end
  1069. function time:_add(tag,value)
  1070. t[tag]=t[tag]+value
  1071. if self._end then
  1072. self._end[tag]=self._end[tag]+value
  1073. end
  1074. end
  1075. function time:add(tag,value)--时间位移--暂且只有在具有该精确值时才生效
  1076. self._add(tag,value)
  1077. self:update()
  1078. end
  1079. function time:getMin()--获取最小精确标签
  1080. return self.accuracy:getMin()
  1081. end
  1082. function time:forceAccuracy()--强制模糊度
  1083. self.accuracy=timeAccuracy.clear
  1084. end
  1085. function time:__connect(other)--连接时间,取前者到后者产生区间。模糊处使用前者补足后者--关于模糊前
  1086. local b=mw.clone(self)
  1087. local e=mw.clone(other)
  1088. b:setEnd(e)
  1089. b:update()
  1090. return b
  1091. end
  1092. function time:__add(other)
  1093. local b=mw.clone(self)
  1094. for _,tag in ipairs(time.baseData) do
  1095. local value=other:getValue(tag)
  1096. if value then
  1097. local v=self:getValue(tag)
  1098. b:_add(tag,v)
  1099. end
  1100. end
  1101. b:update()
  1102. return b
  1103. end
  1104. function time:__sub(other)
  1105. local b=mw.clone(self)
  1106. for _,tag in ipairs(time.baseData) do
  1107. local value=other:getValue(tag)
  1108. if value then
  1109. local v=self:getValue(tag)
  1110. b:_add(tag,-v)
  1111. end
  1112. end
  1113. b:update()
  1114. return b
  1115. end
  1116. function time.currentTimeZone()
  1117. if not time._currentTimeZone then
  1118. local a = os.date('!*t',os.time())--中时区的时间
  1119. local b = os.date('*t',os.time())
  1120. time._currentTimeZone= os.difftime(os.time(b), os.time(a))
  1121. end
  1122. return time._currentTimeZone
  1123. end
  1124. function time.normalizeZone(timezone)
  1125. if timezone == nil or #timezone == 0 then
  1126. return currentTimeZone() --用户当前时区
  1127. else
  1128. local hour, min = mw.ustring.match(mw.text.trim(timezone), "^([-%+]?%d+):?(%d*)$")
  1129. if hour == nil then
  1130. error("时区参数格式不正确。")
  1131. end
  1132. return (tonumber(hour)*60+tonumber(min))*60
  1133. end
  1134. end
  1135. function time:convert(o_timezone,c_timezone)--改变时区
  1136. local ot=time.normalizeZone(o_timezone)
  1137. local ct=time.normalizeZone(c_timezone or mw.getCurrentFrame():callParserFunction( "#var","timezone"))
  1138. self:add("sec",ct-ot)
  1139. end
  1140. function time:setData(t)--设置数据
  1141. for _,tag in ipairs(time.baseData) do
  1142. self[tag]=t[tag]
  1143. end
  1144. end
  1145. function time:sort()--规范数据
  1146. if self._sorted then
  1147. return self
  1148. end
  1149. self.value=self:_getNumber()
  1150. local t=os.date("*t",self.value)
  1151. t.wday=t.wday-1
  1152. if t.wday==0 then t.wday=7 end--ios标准
  1153. self:setData(t)
  1154. local wday=math.mod(self.wday-self.yday,7)
  1155. wday=wday>0 and wday or 7+wday--不包括0
  1156. self.week=math.floor((self.yday+1-self.wday)/7)+(wday>4 and -1 or 0)+2
  1157. if self._end then
  1158. self._end:sort()
  1159. end
  1160. self._sorted=true
  1161. return self
  1162. end
  1163. --文本转换
  1164. function time.sortUnits(uv1,uv2)
  1165. return uv1.unit:priorityCompare(uv2.unit)
  1166. end
  1167. function time.analysis_step(text,index)
  1168. local value
  1169. for n1,group in ipairs(time.analysisTable) do
  1170. for n2,unit in ipairs(group) do
  1171. --mw.log("name",n1,n2,text:sub(index),unit.patternAnalysis)
  1172. value,index=unit:analysis(time,text,index)
  1173. if value then--!需要追加模糊词的处理
  1174. --mw.log("analysis!")
  1175. return unit,value,index
  1176. end
  1177. end
  1178. end
  1179. return nil,nil,index
  1180. end
  1181. function time.analysisSp(analysis_pattern)
  1182. local value
  1183. local trie=time.formatTrie
  1184. local function fuc(text,index)
  1185. local time1=time.create()
  1186. local ni=string.matchTrie(analysis_pattern,trie,text:sub(index),time1)
  1187. return time1,index+ni-1
  1188. end
  1189. return fuc
  1190. end
  1191. function time.analysis_simple(text,index)--处理不含连接符的时间文本
  1192. local unitvalue={}
  1193. local unit,value
  1194. repeat
  1195. repeat--trim
  1196. local b,e=string.findAny(text,time.analysisIgnore,index)--连接符处理,可能需要多段支持
  1197. if b then
  1198. index=e+1
  1199. end
  1200. until(not b)
  1201. --mw.log("analysis!",text:sub(index))
  1202. unit,value,index= time.analysis_step(text,index)
  1203. if unit then
  1204. table.insert(unitvalue,{unit=unit,value=value})
  1205. end
  1206. until(unit==nil or index>#text)
  1207. table.sort(unitvalue,time.sortUnits)--必须保证信息是连成段的,不允许空隙
  1208. local time1=time.create()
  1209. for _,uv in ipairs(unitvalue) do
  1210. uv.unit:supplyTime(time1,uv.value)
  1211. end
  1212. return time1,index
  1213. end
  1214. function time.analysis(text,analysis_pattern)--分析文本
  1215. local analysis=analysis_pattern and time.analysisSp(analysis_pattern) or time.analysis_simple
  1216. local time1,index=analysis(text,1,analysis_pattern)
  1217. local time2
  1218. repeat
  1219. local b,e=string.findAny(text,time.analysisConnect,index)--连接符处理,可能需要多段支持
  1220. if b then
  1221. time2,index=analysis(text,e+1,analysis_pattern)
  1222. end
  1223. until(not b)
  1224. if time2 then
  1225. --error(table.concat({time2.year,time2.month,time2.day},";"))
  1226. time1:setEnd(time2)
  1227. --error(table.concat({time1._end.year,time1._end.month,time1._end.day},";"))
  1228. end
  1229. return time1,index
  1230. end
  1231. function time:format(pattern,ignore)--格式化--使用匹配符,指示忽略粗略描述
  1232. self:sort()
  1233. if self._end then
  1234. self._end:sort()
  1235. end
  1236. local getvalue,accuracy
  1237. if ignore then
  1238. getvalue=time.getValue
  1239. time.getValue=time.getValueIgnore
  1240. elseif ignore==false then
  1241. getvalue=time.getValue
  1242. time.getValue=time.forceGetValue
  1243. end
  1244. local text=string.replaceTrie(pattern,time.formatTrie,self)
  1245. if self._end then
  1246. if self._end:_getNumber()~=self:_getNumber() then
  1247. text=text..self.formatConnect..string.replaceTrie(pattern,time.formatTrie,self._end)
  1248. end
  1249. end
  1250. if getvalue then
  1251. time.getValue=getvalue
  1252. end
  1253. return text--range问题
  1254. end
  1255. function time:__tostring()
  1256. return self:format("%Y%M%D%H%I%S")
  1257. end
  1258. --主函数
  1259. module.time=time--用于继承等
  1260. function module.formatList(frame)--参数表
  1261. local standard,expend,lang=module.initialize()
  1262. local var_array = require("Module:Var-array")
  1263. local formatNames = {}
  1264. local formatList = {}
  1265. table.insert(formatNames,"")
  1266. local list = {}
  1267. for _, unit in pairs(standard) do
  1268. if unit.format then
  1269. table.insert(list, { unit.format, unit.description })
  1270. end
  1271. end
  1272. for _, unit in pairs(expend) do
  1273. if unit.format then
  1274. table.insert(list, { unit.format, unit.description })
  1275. end
  1276. end
  1277. table.insert(formatList,list)
  1278. for name, l in pairs(lang) do
  1279. table.insert(formatNames, name)
  1280. local list = {}
  1281. for _, unit in pairs(l) do
  1282. if unit.format then
  1283. table.insert(list, { unit.format, unit.description })
  1284. end
  1285. end
  1286. table.insert(formatList,list)
  1287. end
  1288. var_array.new("time.convert.formatlist.name", formatNames)
  1289. var_array.new("time.convert.formatlist", formatList)
  1290. end
  1291. function module.toTime(text,analysis_pattern)--获取时间类
  1292. return time.analysis(text or "",analysis_pattern)
  1293. end
  1294. function module.initialize(from,to,connect)--设置参数初始化
  1295. return time.initializeUnit(from,to,connect)
  1296. end
  1297. function module.format(text,pattern,ignore,o_timezone,c_timezone,analysis_pattern)--格式化文本
  1298. assert(text,"text cannot be nil")
  1299. assert(pattern,"pattern cannot be nil")
  1300. local time=time.analysis(text,analysis_pattern)
  1301. if o_timezone then
  1302. time=time:convert(o_timezone,c_timezone)
  1303. end
  1304. return time:format(pattern,ignore)
  1305. end
  1306. function module._main(args)--主函数
  1307. module.initialize(args.from or args["原语言"],args.to or args["目标语言"],args.connect or args["连接符"])
  1308. local text=args[1] or args.text or args["时间文本"]
  1309. local pattern=args[2] or args.pattern or args["格式化字符串"]
  1310. local ignore=args[3] or args.force or args["强制精确度"]
  1311. if ignore=="true" then
  1312. ignore=true
  1313. elseif ignore=="false" then
  1314. ignore=false
  1315. else
  1316. ignore=nil
  1317. end
  1318. local o_timezone=args[4] or args.o_timezone or args.o_tz or args["原时区"]
  1319. local c_timezone=args.c_timezone or args.c_tz or args["现时区"]
  1320. if not pattern then return "" end
  1321. local analysis_pattern=args[5] or args.analysis_pattern or args.a_pattern or args["分析字符串"]
  1322. return module.format(text,pattern,ignore,o_timezone,c_timezone,analysis_pattern)
  1323. end
  1324. function module.main(frame)--主函数
  1325. local args = getArgs(frame)
  1326. return module._main(args)
  1327. end
  1328. return module