/* Mateusz Boryń, grupa I4I3
ZPR, praca domowa, zadanie ZAD60: boost::date_time
*/

/*
Biblioteka boost::date_time służy do reprezentacji i przechowywania
czasu i daty, określania jaka będzie data, np. za 84 dni?,
jaka będzie data i czas za 99 godzin, 11 minut i 50 sekund

*/


/* Dołączenie tego nagłówka pozwala między innymi tworzyć obiekty
typu date i używać je do operacji strumieniowych.
Obiekt klasy date przechowuje datę, to jest dzień, miesiąc i rok.
*/
#include <boost/date_time/gregorian/gregorian.hpp>


/* Dołączenie tego nagłówka pozwala między innymi tworzyć obiekty
typu ptime i używać je do operacji strumieniowych.
Obiekt klasy ptime przechowuje czas z dokładnością do mikrosekund,
a także datę.
*/
#include <boost/date_time/posix_time/posix_time.hpp>

#include <iostream>
#include <string>
#include <sstream>

using namespace std;
using namespace boost::gregorian;
using namespace boost::posix_time;

int main(int argc, char *argv[])
{
	/*	 Najbardziej aktualne pytanie: jaki dziś mamy dzień i która jest teraz godzina?
		w ten sposób tworzymy obiekt, który przechowuje tylko datę
		obiektu tego po skonstruowaniu nie można zmienić, no chyba, że 
		użyje się operatora przypisania
		date jest w boost::gregorian
	*/
	date today(day_clock::local_day());
	cout<<"Dzisiejsza data: "<<today<<endl;
	cout<<"Dzien tygodnia: "<<today.day_of_week()<<endl;
	
	
	
	/* W ten sposób towrzymy obiekt, który przechowuje datę i czas
		obiektu tego po skonstruowaniu nie można zmienić, no chyba, że 
		użyje się operatora przypisania.
		ptime jest w boost::posix_time
	*/
	cout<<endl;
	ptime now(second_clock::local_time());
	cout<<"Aktualny czas i data: "<<now<<endl;
	cout<<"Aktualna data: "<<now.date()<<endl;
	cout<<"Aktualny czas: "<<now.time_of_day()<<endl;
	
	
	/*	Jaka będzie data z 84 dni?
		Używamy obiektu date_duration, który przechowuje długość trwania
		podawaną w dniach i niezależną od daty początkowej
	*/
	cout<<endl;
	date_duration duration_84_days(84); // podajemy liczbę dni
	date in_84_days(today + duration_84_days);
	cout<<"Za 84 dni bedzie: "<<in_84_days<<endl;
	
	/*	jaka będzie data i czas za 99 godzin, 11 minut i 50 sekund?
		używamy obiektu boost::posix_time::time_duration - czas trwania 
		podawany bez żadnego konkretnego momentu w czasie.
		podajemy odpowiednio: liczbę godzin, minut, sekund 
		i ułamki sekund (zależne od sposobu kompilacji)
	*/
	cout<<endl;
	time_duration some_time_duration(99, 11, 50, 0);
	ptime after_some_time = now + some_time_duration;
	ptime before_some_time = now - some_time_duration;
	cout<<"Za 99 godzin, 11 minut i 50 sekund będzie: "<<after_some_time<<endl;
	cout<<"99 godzin, 11 minut i 50 sekund było: "<<before_some_time<<endl;
	cout<<"99 godzin, 11 minut i 50 sekund to po przeliczeniu na sekundy: "
		<<some_time_duration.total_seconds()<<endl;
	
	/*	Ile czasu upłynęło od wejścia Polski do UE? 
		Używamy typu date_period do określenia przedziału czasu 
		Obiekt date konstruujemy z użyciem operatora czytania ze strumienia
	*/
	cout<<endl;
	stringstream accession;
	accession<<"2004-May-01";
	
	date accession_date;
	accession>>accession_date;
	cout<<"Polska przystapila do UE "<<accession_date<<endl;
	date_period Poland_in_the_UE(accession_date, today);
	cout<<"Zatem jest tam juz "<<Poland_in_the_UE.length()<<" dni"<<endl;
	
	date_period kadencja_4(date(2001, Oct, 19), date(2005, Oct, 19));
	date_period kadencja_5(date(2005, Oct, 19), date(2007, Oct, 20));
	
	cout<<"4. kadencja sejmu RP: "<<kadencja_4<<endl;
	cout<<"5. kadencja sejmu RP: "<<kadencja_5<<endl;
	cout<<"Czy Polska przystapila do UE za czwartej kadencji? "
		<<kadencja_4.contains(accession_date)<<endl;
	
	cout<<"Czy kadencja_4 i kadencja_5 sasiaduja? "<<kadencja_4.is_adjacent(kadencja_5)<<endl;
	
	/* Znajdźmy pierwszą niedzielę przyszłego roku.
		obiekt boost::gregorian::first_day_of_the_week_in_month tworzymy podając
		dzień tygodnia i miesiąc, a potem przy pobieraniu daty określamy rok
	*/
	cout<<endl;
	first_day_of_the_week_in_month first_sunday(Sunday, Jan);
	date first_sunday_next_year = first_sunday.get_date(today.year() + 1);
	cout<<"Pierwsza niedziela w przyszlym roku bedzie: "<<first_sunday_next_year<<endl;
	
	/*	Iteratory biblioteki date_time pozwalają m.in. na wypisywanie
		kolejnych dat. Tutaj wypisujemy pięć dat, co tydzień, od dziś
	*/
	cout<<endl;
	week_iterator iter(today);
	for(int i=0; i<5; ++i){
		cout<<"Za "<<i+1<<" tygodni bedzie "<<*++iter<<endl;
	}
	
	/* UWAGA: dodawanie do daty obiektu typu boost::date_duration::months,
		a potem odjęcie nawet tego samego obiektu od uzyskanej daty może powodować,
		że uzyskamy inną datę, niż ta, od której zaczęliśmy.
		Jest to efekt "przyciągania do ostatniego dnia miesiąca":
		Dodając/odejmując miesiąc do/od ostatniego dnia miesiąca, zawsze uzyskamy
		datę, będącą ostatnim dniem miesiąca.
		Tak samo jest dla iteratorów month_iterator
	*/ 
	cout<<endl;
	date some_date(2008, Jan, 30);	// przedostatni dzień stycznia
	cout<<"To jest przedostatni dzien stycznia: "<<some_date<<endl;
	date month_later(some_date + months(1));
	cout<<"Po dodaniu jednego miesiaca: "<<month_later<<endl;
	date not_the_same_date(month_later - months(1));
	cout<<"Po odjeciu jednego miesiaca od "<<month_later
		<<" otrzymujemy "<<not_the_same_date<<endl;
	
	return 0;
}
