农历日历 v1.0.4
载入中...
搜索中...
未找到
LunarTable.cpp
1
6#include "LunarTable.h"
7#include <QDataStream>
8#include <QFile>
9#include <QLoggingCategory>
10#include <QSharedPointer>
11#include "sxtwl.h"
12
13static Q_LOGGING_CATEGORY(Logger, "Rabbit.LunarCalendar.table")
14
15static const QString g_Signature = "Lunar cache table. Author: Kang Lin(kl222@126.com)";
17 const QDate& min,
18 const QDate& max,
19 bool bCached,
20 QObject *parent)
21 : QThread(parent),
22 m_pTable(pTable),
23 m_minDate(min),
24 m_maxDate(max),
25 m_bCached(bCached)
26{}
27
28void CThreadGenerate::run()
29{
30 qDebug(Logger) << "CThreadGenerate::run()";
31 if(!m_pTable) return;
32 m_pTable->Generate(m_minDate, m_maxDate, m_bCached);
33}
34
35CLunarTable::CLunarTable(QObject *parent) : QObject(parent)
36{
37 m_bSaveAllDate = true;
38 m_nThreadNumber = 0;
39 Load(":/data/LunarCalendarTable");
40}
41
42CLunarTable* CLunarTable::Instance()
43{
44 static CLunarTable* p = nullptr;
45 if(nullptr == p)
46 p = new CLunarTable();
47 return p;
48}
49
50#ifndef QT_NO_DATASTREAM
51QDataStream& operator << (QDataStream& output, const CLunarTable::_LUNAR_DAY& data)
52{
53 output << data.nTg
54 << data.nDz
55 << data.bLeap
56 << data.nYear
57 << data.nMonth
58 << data.nDay
59 << data.nJq;
60 return output;
61}
62
63QDataStream& operator >> (QDataStream& input, CLunarTable::_LUNAR_DAY& data)
64{
65 input >> data.nTg
66 >> data.nDz
67 >> data.bLeap
68 >> data.nYear
69 >> data.nMonth
70 >> data.nDay
71 >> data.nJq;
72 return input;
73}
74#endif
75
76int CLunarTable::Save(const QString &file, bool bAll)
77{
78 int nRet = 0;
79 //TODO: modify the nVersion when modify data format
80 uint8_t nVersion = 0;
81
82 QFile f(file);
83 if(!f.open(QIODevice::WriteOnly))
84 {
85 qCritical(Logger) << "Open file fail: " << file;
86 return -1;
87 }
88
89 if(!bAll)
90 CleanOutsideRange(m_minDate, m_maxDate);
91
92 QDataStream out(&f);
93 out << g_Signature;
94 out << nVersion;
95 out << static_cast<qint64>(m_Lunar.size());
96 QMap<qint64, _LUNAR_DAY>::iterator it;
97 for(it = m_Lunar.begin(); it != m_Lunar.end(); it++)
98 {
99 out << it.key();
100 out << it.value();
101 }
102
103 f.close();
104 return nRet;
105}
106
107int CLunarTable::Load(const QString &file)
108{
109 int nRet = 0;
110 uint8_t nVersion = 0;
111 QString signature;
112 QFile f(file);
113 if(!f.open(QIODevice::ReadOnly))
114 {
115 qCritical() << "Open file fail: " << file;
116 return -1;
117 }
118 QDataStream in(&f);
119 in >> signature;
120 if(g_Signature != signature)
121 {
122 qCritical() << "Luanar table Signature error: " << signature;
123 f.close();
124 return -2;
125 }
126 in >> nVersion;
127 //TODO: check version
128 switch (nVersion) {
129 case 0:
130 nRet = LoadVersion0(in);
131 break;
132 default:
133 qCritical() << "Luanar table version[" << nVersion << "] don't support";
134 break;
135 }
136
137 f.close();
138 return nRet;
139}
140
141int CLunarTable::LoadVersion0(QDataStream &in)
142{
143 qint64 nNum = 0;
144 in >> nNum;
145 m_Lunar.clear();
146 while(nNum--)
147 {
148 qint64 jd;
149 in >> jd;
150 _LUNAR_DAY lunar;
151 in >> lunar;
152 m_Lunar[jd] = lunar;
153 }
154 return 0;
155}
156
157int CLunarTable::Generate(const QDate &min, const QDate &max, const QString &szFile, int nThread, bool bClearCache, bool bSaveAllDate)
158{
159 int nRet = 0;
160 if(bClearCache)
161 m_Lunar.clear();
162 m_nThreadNumber = nThread;
163 m_szFile = szFile;
164 m_minDate = min;
165 m_maxDate = max;
166 m_bSaveAllDate = bSaveAllDate;
167 CThreadGenerate* pGenerate = nullptr;
168 qint64 days = min.daysTo(max);
169 qint64 num = days / nThread;
170 QDate d = min;
171 for(int i = 1; i <= nThread; i++)
172 {
173 QDate maxDate;
174 if(i == nThread)
175 maxDate = max;
176 else
177 maxDate = d.addDays(num);
178 pGenerate = new CThreadGenerate(this, d, maxDate, !bClearCache, this);
179 d = maxDate.addDays(1);
180 if(pGenerate)
181 {
182 bool check = false;
183 check = connect(pGenerate, SIGNAL(finished()),
184 this, SLOT(slotGenerateFinished()));
185 Q_ASSERT(check);
186 check = connect(pGenerate, SIGNAL(finished()),
187 pGenerate, SLOT(deleteLater()));
188 Q_ASSERT(check);
189 pGenerate->start();
190 }
191
192 }
193
194 return nRet;
195}
196
197void CLunarTable::slotGenerateFinished()
198{
199 qDebug(Logger) << "Thread finished: " << m_nThreadNumber;
200 if(--m_nThreadNumber)
201 return;
202 if(m_szFile.isEmpty())
203 {
204 qCritical(Logger()) << "Cache file is empty";
205 return;
206 }
207 int nRet = Save(m_szFile, m_bSaveAllDate);
208 if(!nRet)
209 qInfo(Logger) << "Generate finished: save to:" << m_szFile;
210 else
211 qCritical(Logger) << "Generate finished: save fail" << nRet << ";" << m_szFile ;
212}
213
214int CLunarTable::Generate(const QDate &min, const QDate &max, bool bUseCached)
215{
216 int nRet = 0;
217 if(!min.isValid() || !max.isValid())
218 return -1;
219
220 QDate date = min;
221 while(date.isValid() && date <= max)
222 {
223 if(bUseCached)
224 {
225 auto it = m_Lunar.find(date.toJulianDay());
226 if(it != m_Lunar.end())
227 {
228 date = date.addDays(1);
229 continue;
230 }
231 }
232
233 _LUNAR_DAY lunar;
234 nRet = GetLunar(date, lunar, false);
235 if(nRet) break;
236
237 m_GenerateMutex.lock();
238 m_Lunar[date.toJulianDay()] = lunar;
239 m_GenerateMutex.unlock();
240
241 date = date.addDays(1);
242 }
243
244 return nRet;
245}
246
247int CLunarTable::GetLunar(const QDate &date, _LUNAR_DAY &lunar, bool cache)
248{
249 int nRet = -1;
250 if(!date.isValid())
251 return nRet;
252
253 if(cache) {
254 auto it = m_Lunar.find(date.toJulianDay());
255 if(m_Lunar.end() != it)
256 {
257 lunar = *it;
258 return 0;
259 }
260 }
261
262 QSharedPointer<Day> pDay(sxtwl::fromSolar(date.year(), date.month(), date.day()));
263 Day& day = *pDay;
264
265 //TODO:同步修改 CLunarTable::Generate 中
266 //以立春为农历新年第一天
267// lunar.nTg = day.Lyear2.tg;
268// lunar.nDz = day.Lyear2.dz;
269 //以春节为农历新年第一天
270 lunar.nTg = day.getYearGZ().tg;
271 lunar.nDz = day.getYearGZ().dz;
272
273 lunar.bLeap = day.isLunarLeap();
274 lunar.nYear = day.getLunarYear();
275 lunar.nMonth = day.getLunarMonth();
276 if(lunar.nMonth > 12 || lunar.nMonth < 1)
277 qCritical(Logger) << "Lunar month error, data:" << date;
278 lunar.nDay = day.getLunarDay();
279 if(lunar.nDay > 31 || lunar.nDay < 1)
280 qCritical(Logger) << "Lunar day error, date:" << date;
281
282 if(day.hasJieQi())
283 lunar.nJq = day.getJieQi();
284 else
285 lunar.nJq = -1;
286
287 return 0;
288}
289
290int CLunarTable::CleanOutsideRange(const QDate &min, const QDate &max)
291{
292 if(!min.isValid() || !max.isValid())
293 return -1;
294 QMap<qint64, _LUNAR_DAY>::iterator it;
295 for(it = m_Lunar.begin(); it != m_Lunar.end();)
296 {
297 qint64 key = it.key();
298 it++;
299 if(key < min.toJulianDay() || key > max.toJulianDay())
300 {
301 m_Lunar.remove(key);
302 }
303 }
304 return 0;
305}
产生、保存、加载农历缓存。用于提高性能。
Definition LunarTable.h:21
int GetLunar(const QDate &date, _LUNAR_DAY &lunar, bool cache=true)
得到指定日期的农历