00001
00007 #include <cassert>
00008
00009 #include <Utilitarios/ignoradores.H>
00010 #include <Erros/erros.H>
00011
00012
00013
00014
00015 inline bool Utilitarios::eBissexto(Ano const ano)
00016 {
00017 return ano % 4 == 0 and (ano % 100 != 0 or ano % 400 == 0);
00018 }
00019
00020 inline int Utilitarios::numeroDeDiasEm(Mes const mes, Ano const ano)
00021 {
00022 assert(janeiro <= mes and mes <= dezembro);
00023
00024 static int numero_de_dias[numero_total_de_meses + 1][2] = {
00025 {0, 0},
00026 {31, 31},
00027 {28, 29},
00028 {31, 31},
00029 {30, 30},
00030 {31, 31},
00031 {30, 30},
00032 {31, 31},
00033 {31, 31},
00034 {30, 30},
00035 {31, 31},
00036 {30, 30},
00037 {31, 31}
00038 };
00039
00040 return numero_de_dias[mes][eBissexto(ano)];
00041 }
00042
00043
00044
00045
00046 inline Utilitarios::Mes& Utilitarios::operator++(Mes& mes)
00047 {
00048 assert(janeiro <= mes and mes <= dezembro);
00049
00050 if(mes == dezembro)
00051 mes = janeiro;
00052 else
00053 mes = Mes(int(mes) + 1);
00054
00055 return mes;
00056 }
00057
00058 inline Utilitarios::Mes& Utilitarios::operator--(Mes& mes)
00059 {
00060 assert(janeiro <= mes and mes <= dezembro);
00061
00062 if(mes == janeiro)
00063 mes = dezembro;
00064 else
00065 mes = Mes(int(mes) - 1);
00066
00067 return mes;
00068 }
00069
00070 inline Utilitarios::Mes Utilitarios::operator++(Mes& mes, int)
00071 {
00072 assert(janeiro <= mes and mes <= dezembro);
00073
00074 Mes mes_antigo = mes;
00075 ++mes;
00076
00077 return mes_antigo;
00078 }
00079
00080 inline Utilitarios::Mes Utilitarios::operator--(Mes& mes, int)
00081 {
00082 assert(janeiro <= mes and mes <= dezembro);
00083
00084 Mes mes_antigo = mes;
00085 --mes;
00086
00087 return mes_antigo;
00088 }
00089
00090 inline Utilitarios::Mes& Utilitarios::operator+=(Mes& mes,
00091 int numero_de_meses)
00092 {
00093 assert(janeiro <= mes and mes <= dezembro);
00094
00095 if(numero_de_meses < 0)
00096 numero_de_meses = numero_total_de_meses -
00097 (-numero_de_meses % numero_total_de_meses);
00098
00099 mes = Mes((int(mes) - 1 + numero_de_meses) % numero_total_de_meses + 1);
00100
00101 return mes;
00102 }
00103
00104 inline Utilitarios::Mes& Utilitarios::operator-=(Mes& mes,
00105 int const numero_de_meses)
00106 {
00107 assert(janeiro <= mes and mes <= dezembro);
00108
00109 mes += -numero_de_meses;
00110
00111 return mes;
00112 }
00113
00114 inline Utilitarios::Mes Utilitarios::operator+(Mes mes,
00115 int const numero_de_meses)
00116 {
00117 assert(janeiro <= mes and mes <= dezembro);
00118
00119 mes += numero_de_meses;
00120
00121 return mes;
00122 }
00123
00124 inline Utilitarios::Mes Utilitarios::operator+(int const numero_de_meses,
00125 Mes mes)
00126 {
00127 assert(janeiro <= mes and mes <= dezembro);
00128
00129 return mes + numero_de_meses;
00130 }
00131
00132 inline int Utilitarios::operator-(Mes const um_mes, Mes const outro_mes)
00133 {
00134 assert(janeiro <= um_mes and um_mes <= dezembro and
00135 janeiro <= outro_mes and outro_mes <= dezembro);
00136
00137 if(um_mes >= outro_mes)
00138 return int(um_mes) - int(outro_mes);
00139 else
00140 return numero_total_de_meses + int(um_mes) - int(outro_mes);
00141 }
00142
00143 inline Utilitarios::Mes Utilitarios::operator-(Mes mes,
00144 int const numero_de_meses)
00145 {
00146 assert(janeiro <= mes and mes <= dezembro);
00147
00148 return mes + -numero_de_meses;
00149 }
00150
00151 inline std::ostream& Utilitarios::operator<<(std::ostream& saida,
00152 Mes const mes)
00153 {
00154 assert(janeiro <= mes and mes <= dezembro);
00155
00156 return saida << nomes_dos_meses[mes];
00157 }
00158
00159
00160
00161
00162 inline
00163 Utilitarios::DiaDaSemana& Utilitarios::operator++(DiaDaSemana& dia_da_semana)
00164 {
00165 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00166
00167 if(dia_da_semana == sabado)
00168 dia_da_semana = domingo;
00169 else
00170 dia_da_semana = DiaDaSemana(int(dia_da_semana) + 1);
00171
00172 return dia_da_semana;
00173 }
00174
00175 inline
00176 Utilitarios::DiaDaSemana& Utilitarios::operator--(DiaDaSemana& dia_da_semana)
00177 {
00178 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00179
00180 if(dia_da_semana == domingo)
00181 dia_da_semana = sabado;
00182 else
00183 dia_da_semana = DiaDaSemana(int(dia_da_semana) - 1);
00184
00185 return dia_da_semana;
00186 }
00187
00188 inline
00189 Utilitarios::DiaDaSemana Utilitarios::operator++(DiaDaSemana& dia_da_semana,
00190 int)
00191 {
00192 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00193
00194 DiaDaSemana dia_antigo = dia_da_semana;
00195 ++dia_da_semana;
00196
00197 return dia_antigo;
00198 }
00199
00200 inline
00201 Utilitarios::DiaDaSemana Utilitarios::operator--(DiaDaSemana& dia_da_semana,
00202 int)
00203 {
00204 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00205
00206 DiaDaSemana dia_antigo = dia_da_semana;
00207 --dia_da_semana;
00208
00209 return dia_antigo;
00210 }
00211
00212 inline
00213 Utilitarios::DiaDaSemana& Utilitarios::operator+=(DiaDaSemana& dia_da_semana,
00214 int numero_de_dias)
00215 {
00216 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00217
00218 if(numero_de_dias < 0)
00219 numero_de_dias = numero_total_de_dias_da_semana -
00220 (-numero_de_dias % numero_total_de_dias_da_semana);
00221
00222 dia_da_semana = DiaDaSemana((int(dia_da_semana) + numero_de_dias) %
00223 numero_total_de_dias_da_semana);
00224
00225 return dia_da_semana;
00226 }
00227
00228 inline
00229 Utilitarios::DiaDaSemana& Utilitarios::operator-=(DiaDaSemana& dia_da_semana,
00230 int const numero_de_dias)
00231 {
00232 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00233
00234 return dia_da_semana += -numero_de_dias;
00235 }
00236
00237 inline
00238 Utilitarios::DiaDaSemana Utilitarios::operator+(DiaDaSemana dia_da_semana,
00239 int const numero_de_dias)
00240 {
00241 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00242
00243 dia_da_semana += numero_de_dias;
00244
00245 return dia_da_semana;
00246 }
00247
00248 inline Utilitarios::DiaDaSemana
00249 Utilitarios::operator+(int const numero_de_dias,
00250 DiaDaSemana const dia_da_semana)
00251 {
00252 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00253
00254 return dia_da_semana + numero_de_dias;
00255 }
00256
00257 inline int Utilitarios::operator-(DiaDaSemana const um_dia_da_semana,
00258 DiaDaSemana const outro_dia_da_semana)
00259 {
00260 assert(domingo <= um_dia_da_semana and um_dia_da_semana <= sabado and
00261 domingo <= outro_dia_da_semana and outro_dia_da_semana <= sabado);
00262
00263 if(um_dia_da_semana >= outro_dia_da_semana)
00264 return int(um_dia_da_semana) - int(outro_dia_da_semana);
00265 else
00266 return numero_total_de_dias_da_semana +
00267 int(um_dia_da_semana) - int(outro_dia_da_semana);
00268 }
00269
00270 inline Utilitarios::DiaDaSemana
00271 Utilitarios::operator-(DiaDaSemana const dia_da_semana,
00272 int const numero_de_dias)
00273 {
00274 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00275
00276 return dia_da_semana + -numero_de_dias;
00277 }
00278
00279 inline std::ostream& Utilitarios::operator<<(std::ostream& saida,
00280 DiaDaSemana const dia_da_semana)
00281 {
00282 assert(domingo <= dia_da_semana and dia_da_semana <= sabado);
00283
00284 saida << nomes_dos_dias_da_semana[dia_da_semana];
00285
00286 return saida;
00287 }
00288
00289
00290
00291
00292 inline Utilitarios::Data::Data(Ano const ano, Mes const mes, Dia const dia)
00293 : ano_(ano), mes_(mes), dia_(dia)
00294 {
00295 assert(ano_minimo <= ano and
00296 janeiro <= mes and mes <= dezembro and
00297 1 <= dia and dia <= numeroDeDiasEm(mes, ano));
00298
00299 assert(cumpreInvariante());
00300 }
00301
00302 inline Utilitarios::Data::Data()
00303 : ano_(2003), mes_(janeiro), dia_(1)
00304 {
00305
00306 assert(cumpreInvariante());
00307 }
00308
00309 inline Utilitarios::Data::Data(long const dia_juliano)
00310 {
00311 long l = dia_juliano + 68569;
00312
00313 long const n = (4 * l) / 146097;
00314
00315 l -= (146097 * n + 3) / 4;
00316
00317 long const i = (4000 * (l + 1)) / 1461001;
00318
00319 l += -(1461 * i) / 4 + 31;
00320
00321 long const j = (80 * l) / 2447;
00322
00323 dia_ = Dia(l - (2447 * j) / 80);
00324
00325 l = j / 11;
00326
00327 mes_ = Mes(j + 2 - (12 * l));
00328 ano_ = Ano(100 * (n - 49) + i + l);
00329
00330 assert(cumpreInvariante());
00331 }
00332
00333 inline Utilitarios::Ano const& Utilitarios::Data::ano() const
00334 {
00335 assert(cumpreInvariante());
00336
00337 return ano_;
00338 }
00339
00340 inline Utilitarios::Mes const& Utilitarios::Data::mes() const
00341 {
00342 assert(cumpreInvariante());
00343
00344 return mes_;
00345 }
00346
00347 inline Utilitarios::Dia const& Utilitarios::Data::dia() const
00348 {
00349 assert(cumpreInvariante());
00350
00351 return dia_;
00352 }
00353
00354 inline Utilitarios::DiaDaSemana Utilitarios::Data::diaDaSemana() const
00355 {
00356 assert(cumpreInvariante());
00357
00358 return DiaDaSemana((diaJuliano() + 1) % numero_total_de_dias_da_semana);
00359 }
00360
00361 inline long int Utilitarios::Data::diaJuliano() const
00362 {
00363 assert(cumpreInvariante());
00364
00365 return ((1461 * (ano_ + 4800 + (int(mes_) - 14) / 12)) / 4 +
00366 (367 * (int(mes_) - 2 - 12 * ((int(mes_) - 14) / 12))) / 12 -
00367 (3 * ((ano_ + 4900 + (int(mes_) - 14) / 12) / 100)) / 4 +
00368 dia_ - 32075);
00369 }
00370
00371 inline int Utilitarios::Data::numeroDeDiasNoMes() const
00372 {
00373 assert(cumpreInvariante());
00374
00375 return numeroDeDiasEm(mes_, ano_);
00376 }
00377
00378 inline bool Utilitarios::Data::anoEBissexto() const
00379 {
00380 assert(cumpreInvariante());
00381
00382 return eBissexto(ano_);
00383 }
00384
00385 inline Utilitarios::Data::Data(std::istream& entrada)
00386 {
00387 assert(entrada);
00388
00389 int mes;
00390
00391 entrada >> ano_ >> il
00392 >> mes >> il
00393 >> dia_ >> il;
00394
00395 if(mes < janeiro or dezembro < mes)
00396 throw Erros::ErroAoCarregar("Utilitarios::Data");
00397
00398 mes_ = Mes(mes);
00399
00400 if(not entrada or not cumpreInvariante())
00401 throw Erros::ErroAoCarregar("Utilitarios::Data");
00402
00403 assert(cumpreInvariante());
00404 }
00405
00406 inline void Utilitarios::Data::carregaDe(std::istream& entrada)
00407 {
00408 assert(cumpreInvariante());
00409 assert(entrada);
00410
00411 *this = Data(entrada);
00412
00413 assert(cumpreInvariante());
00414 }
00415
00416 inline void Utilitarios::Data::guardaEm(std::ostream& saida) const
00417 {
00418 assert(cumpreInvariante());
00419 assert(saida);
00420
00421 saida << ano_ << std::endl
00422 << int(mes_) << std::endl
00423 << dia_ << std::endl;
00424
00425 if(not saida)
00426 throw Erros::ErroAoGuardar("Utilitarios::Data");
00427 }
00428
00429 inline Utilitarios::Data& Utilitarios::Data::operator++()
00430 {
00431 assert(cumpreInvariante());
00432
00433 *this += 1;
00434
00435 assert(cumpreInvariante());
00436
00437 return *this;
00438 }
00439
00440 inline Utilitarios::Data& Utilitarios::Data::operator--()
00441 {
00442 assert(cumpreInvariante());
00443 assert(Data(ano_minimo, janeiro, 1) + 1 <= *this);
00444
00445 *this -= 1;
00446
00447 assert(cumpreInvariante());
00448
00449 return *this;
00450 }
00451
00452 inline Utilitarios::Data Utilitarios::Data::operator++(int)
00453 {
00454 assert(cumpreInvariante());
00455
00456 Data data_anterior = *this;
00457 ++*this;
00458
00459 assert(cumpreInvariante());
00460
00461 return data_anterior;
00462 }
00463
00464 inline Utilitarios::Data Utilitarios::Data::operator--(int)
00465 {
00466 assert(cumpreInvariante());
00467 assert(Data(ano_minimo, janeiro, 1) + 1 <= *this);
00468
00469 Data data_anterior = *this;
00470 --*this;
00471
00472 assert(cumpreInvariante());
00473
00474 return data_anterior;
00475 }
00476
00477
00478 inline Utilitarios::Data& Utilitarios::Data::operator+=(Duracao const& duracao)
00479 {
00480 assert(cumpreInvariante());
00481 assert(0 <= duracao or Data(ano_minimo, janeiro, 1) - duracao <= *this);
00482
00483 *this = *this + duracao;
00484
00485 assert(cumpreInvariante());
00486
00487 return *this;
00488 }
00489
00490 inline Utilitarios::Data& Utilitarios::Data::operator-=(Duracao const& duracao)
00491 {
00492 assert(cumpreInvariante());
00493 assert(duracao <= 0 or Data(ano_minimo, janeiro, 1) + duracao <= *this);
00494
00495 *this = *this - duracao;
00496
00497 assert(cumpreInvariante());
00498
00499 return *this;
00500 }
00501
00502 inline void Utilitarios::Data::estabeleceDataActualPedidaAoUtilizador()
00503 {
00504 data_actual_obtida_do_sistema = false;
00505 }
00506
00507 inline void Utilitarios::Data::estabeleceDataActualObtidaDoSistema()
00508 {
00509 data_actual_obtida_do_sistema = true;
00510 }
00511
00512 inline bool Utilitarios::Data::cumpreInvariante() const
00513 {
00514 return ano_minimo <= ano_ and
00515 0 < dia_ and dia_ <= numeroDeDiasEm(mes_, ano_);
00516 }
00517
00518 inline bool Utilitarios::operator==(Data const& uma_data,
00519 Data const& outra_data)
00520 {
00521 return uma_data.ano() == outra_data.ano() and
00522 uma_data.mes() == outra_data.mes() and
00523 uma_data.dia() == outra_data.dia();
00524 }
00525
00526 inline bool Utilitarios::operator!=(Data const& uma_data,
00527 Data const& outra_data)
00528 {
00529 return not (uma_data == outra_data);
00530 }
00531
00532 inline bool Utilitarios::operator<(Data const& uma_data,
00533 Data const& outra_data)
00534 {
00535 return uma_data.diaJuliano() < outra_data.diaJuliano();
00536 }
00537
00538 inline bool Utilitarios::operator>(Data const& uma_data,
00539 Data const& outra_data)
00540 {
00541 return outra_data < uma_data;
00542 }
00543
00544 inline bool Utilitarios::operator<=(Data const& uma_data,
00545 Data const& outra_data)
00546 {
00547 return not (uma_data > outra_data);
00548 }
00549
00550 inline bool Utilitarios::operator>=(Data const& uma_data,
00551 Data const& outra_data)
00552 {
00553 return not (uma_data < outra_data);
00554 }
00555
00556 inline Utilitarios::Duracao Utilitarios::operator-(Data const& uma_data,
00557 Data const& outra_data)
00558 {
00559 return uma_data.diaJuliano() - outra_data.diaJuliano();
00560 }
00561
00562 inline Utilitarios::Data Utilitarios::operator-(Data const& data,
00563 Duracao const& duracao)
00564 {
00565 assert(duracao <= 0 or
00566 Data(Data::ano_minimo, janeiro, 1) + duracao <= data);
00567
00568 return data + -duracao;
00569 }
00570
00571 inline Utilitarios::Data Utilitarios::operator+(Data const& data,
00572 Duracao const& duracao)
00573 {
00574 assert(0 <= duracao or
00575 Data(Data::ano_minimo, janeiro, 1) - duracao <= data);
00576
00577 return Data(data.diaJuliano() + duracao);
00578 }
00579
00580 inline Utilitarios::Data Utilitarios::operator+(Duracao const& duracao,
00581 Data const& data)
00582 {
00583 assert(0 <= duracao or
00584 Data(Data::ano_minimo, janeiro, 1) - duracao <= data);
00585
00586 return Data(data.diaJuliano() + duracao);
00587 }
00588
00589 inline std::ostream& Utilitarios::operator<<(std::ostream& saida,
00590 Data const& data)
00591 {
00592 return saida << data.ano() << '/' << int(data.mes()) << '/' << data.dia();
00593 }