DateTime operator+ (const DateTime& first, const YearMonthDuration& second)
{
    int year = first.Year();
    int month = first.Month() - 1;
    int day = first.Day();

    month += second.Months();

    int monthrem = month % 12;
    if (monthrem < 0)
    {
        monthrem += 12;
    }
    year += second.Years() + (month - monthrem) / 12;
    month = monthrem;

    if (DateTime::IsLeapYear(year))
    {
        if (day > (int) monthStartLeap[month + 1] - (int) monthStartLeap[month])
            day = (int) monthStartLeap[month + 1] - (int) monthStartLeap[month];
    }
    else
    {
        if (day > (int) monthStart[month + 1] - (int) monthStart[month])
            day = (int) monthStart[month + 1] - (int) monthStart[month];
    }

    return DateTime(year, month + 1, day, first.Hour(), first.Minute(), first.Second(), first.Timezone());
}
/// calculates day number (with time fractional part)
double DayNumber(const DateTime& dt)
{
   int iYear = dt.Year() - 2000;
   int d = 367 * iYear -
      int(7 * ( iYear + (dt.Month()+9)/12 ) / 4) +
      int(275*dt.Month()/9) + dt.Day() - 730530;

   double UT = CalcUT(dt);
   return d + UT/24.0;
}
// Event callback
static void PEERSDK_CALLBACK OnVideoArrived(void* tag, PeerSDK::VideoArrivedEventArgs const& args)
{
    PeerStreamImpl* impl = (PeerStreamImpl*)tag;
    JNIEnv* env = GetJNIEnvAttachThread();

    jobject listener = env->GetObjectField(impl->getObject(), fields.videoArrivedListener);

    DateTime time = args.Time();
    jobject _time = env->NewObject(clazz.Date, methods.Date_Init,
                                   time.Year(), time.Month(), time.Day(), time.Minute(), time.Second());

    jobject _args = env->NewObject(clazz.VideoArrivedEventArgs, methods.VideoArrivedEventArgs_Init,
                                   args.Type(), args.Channel(), args.BufferLength(), (jint)args.Buffer(),
                                   args.PTS(), args.Width(), args.Height(), 1.0, _time);

    env->CallVoidMethod(listener, methods.VideoArrivedListener_OnVideoArrived, impl->getObject(), _args);

    JNIEnvDeattachThread();
}
void  ImportGPSDataGPGGA (const KKStr&  fileName)
{
  RunLog  log;

  DataBasePtr  dbConn = new DataBase (log);

  ifstream  i (fileName.Str ());
  if  (!i.is_open ())
  {
    log.Level (-1) << endl << endl 
       << "ImpotrtGPSData  Could not open file[" << fileName << "]" << endl
       << endl;
    return;
  }
  log.Level (10) << endl << endl << endl << endl << endl
    << "ImpotrtGPSData   FileName[" << fileName << "]" << endl << endl
    << endl;

  char  buff[20480];
  bool  firstPass = true;

  int  lastMinute = 0;
  int  linesRead = 0;

  KKStr  ln (256);

  DateTime  lastDateTime;
  while  (i.getline (buff, sizeof (buff)))
  {
    linesRead++;
    ln = buff;
    ln.TrimLeft ();
     
    if  (!ln.LocateStr ("GPGGA"))
      continue;

    VectorKKStr  fields = ln.Parse (",");
    if  (fields.size () < 8)
      continue;

    if  (!fields[2].EqualIgnoreCase ("$GPGGA"))
      continue;


    /*
    0           1             2        3         4      5       6       7   8  
06/01/2010, 23:59:59.818,  $GPGGA,  235958,  2840.927,  N,  08828.458,  W,  2,  09,22.10,0,M,,,14,0000*12
06/02/2010, 00:00:10.818,  $GPGGA,  000009,  2840.931,  N,  08828.482,  W,  1,  09,0.89,0,M,,,,*2D
06/02/2010, 00:00:21.802,  $GPGGA,  000020,  2840.929,  N,  08828.505,  W,  1,  09,0.89,0,M,,,,*21
06/02/2010, 00:00:31.818,  $GPGGA,  000030,  2840.924,  N,  08828.526,  W,  1,  09,0.89,0,M,,,,*2C
06/02/2010, 00:00:42.818,  $GPGGA,  000041,  2840.917,  N,  08828.547,  W,  1,  09,0.89,0,M,,,,*2D
06/02/2010, 00:00:53.802,  $GPGGA,  000052,  2840.906,  N,  08828.568,  W,  1,  09,1.00,0,M,,,,*22
06/02/2010, 00:01:03.802,  $GPGGA,  000102,  2840.895,  N,  08828.585,  W,  1,  09,0.89,0,M,,,,*2E
06/02/2010, 00:01:13.818,  $GPGGA,  000112,  2840.883,  N,  08828.600,  W,  1,  09,0.89,0,M,,,,*26
   */


    KKStr  dateStr = fields[0];
    KKStr  timeStr = fields[1];

    KKStr  latStr = fields[4];
    KKStr  logStr = fields[6];

    auto  x = latStr.LocateCharacter ('.');
    if  (!x) 
      continue;

    KKStr latMinStr = latStr.SubStrPart (x - 2);
    KKStr latDegStr = latStr.SubStrSeg (0, x - 2);

    double latitude = latDegStr.ToDouble () + latMinStr.ToDouble () / 60.0;
    if  (fields[5].EqualIgnoreCase ("S"))
      latitude = 0.0 - latitude;

    x = logStr.LocateCharacter ('.');
    if  (!x) 
      continue;

    KKStr logMinStr = logStr.SubStrPart (x - 2);
    KKStr logDegStr = logStr.SubStrSeg (0, x - 2);

    double longitude = logDegStr.ToDouble () + logMinStr.ToDouble () / 60.0;
    if  (fields[7].EqualIgnoreCase ("W"))
      longitude = 0.0 - longitude;

    DateType  gmtDate (dateStr);
    TimeType  gmtTime (timeStr);

    DateTime  gmtDateTime (gmtDate, gmtTime);
    DateTime  localTime = gmtDateTime;
    localTime.HoursAdd (-4);

    DateTime  startDT = localTime;
    DateTime  endDT   = localTime;

    if  (firstPass)
    {
      firstPass = false;
      startDT.SecondsAdd (-180);
    }
    else
    {
      DateTime deltaDT = localTime - lastDateTime;
      long  deltaSecs = (long)deltaDT.Seconds ();
      startDT.SecondsAdd (-(deltaSecs / 2));
    }

    endDT.SecondsAdd (30);

    if  (gmtTime.Minute () != lastMinute)
    {
      lastMinute = gmtTime.Minute ();
      log.Level (10) << "LinesRead[" << linesRead << "]  File[" << osGetRootName (fileName) << "]  GMT Time[" << gmtDate.MMM_DD_YYYY () << " - " << gmtTime.HH_MM_SS () << "]" << endl;
    }

    if  ((endDT.Month () < 6)  &&  (endDT.Day () < 28))
    {
    }
    else
    {
      dbConn->InstrumentDataUpdateLatitudeAndLongitude (startDT, endDT, latitude, longitude);
    }

    lastDateTime = localTime;
  }

  i.close ();

  delete  dbConn;
  dbConn = NULL;
}  /* ImportGPSDataGPGGA */
//----------------------------------------------------------------------------
bool ApplicationBase::Initlize ()
{
	if (msIsInitlized)
		return true;

	// srand
	time_t ti;
	time(&ti);
	srand((unsigned int)ti);

#ifdef PX2_USE_MEMORY
	Memory::Initialize();
#endif

	StringHelp::Initlize();
	FString::Initlize();

	Logger *logger = new0 Logger();

#if defined(_WIN32) || defined(WIN32)
	logger->AddFileHandler("PX2Application_Log.txt", LT_INFO|LT_ERROR|LT_USER);
#endif
	logger->AddOutputWindowHandler(LT_INFO|LT_ERROR|LT_USER);
	logger->StartLogger();

	InitializeNetwork();

	DateTime time;
	int year1 = time.Year();
	int month1 = time.Month();
	int week1 = time.Week();
	int day1 = time.Day();
	int dayOfWeek1 = time.DayOfWeek();
	int dayOfYear1 = time.DayOfYear();
	int hour1 = time.Hour();
	int minute1 = time.Minute();
	int second1 = time.Second();
	int millisecond1 = time.Millisecond();
	int microsecond1 = time.Microsecond();
	PX2_LOG_INFO("Year:%d; Month:%d; Week:%d; Day:%d; DayOfWeek:%d; DayOfYear:%d; Hour:%d; Minute:%d; Second:%d; Millisecond:%d; Microsecond:%d",
		year1, month1, week1, day1, dayOfWeek1, dayOfYear1, hour1, minute1, second1, millisecond1, microsecond1);

	PX2_LOG_INFO("Begin ApplicationBase::Initlize.");

	mTimerMan = new0 TimerManager();

	mIMEDisp = new0 IMEDispatcher();
	PX2_UNUSED(mIMEDisp);

	mLanguageMan = new0 LanguageManager();

	mResMan = new0 ResourceManager();
	PX2_LM.Add("Data/engine/engineLanguage.csv");

	mEventWorld = new0 EventWorld();
	mEventWorld->ComeIn(this);

#if defined (PX2_LUA)
	mScriptMan = ScriptManager::Create(ScriptManager::ST_LUA);
	LuaManager *luaMan = (LuaManager*)mScriptMan;
	tolua_PX2_open(luaMan->GetLuaState());
#endif
	mScriptEventHandler = new0 ScriptEventHandler();
	mEventWorld->ComeIn(mScriptEventHandler);

	mRoot = new0 GraphicsRoot();
	mRoot->Initlize();

	//mDBM = new0 DynamicBufferManager();
	//mDBM->Initlize();

	mGameMan = new0 GameManager();
	mGameMan->LoadBoost("Data/boost.xml");
	int width = mGameMan->GetBoostWidth();
	int height = mGameMan->GetBoostHeight();
#ifdef __MARMALADE__
	width = s3eSurfaceGetInt(S3E_SURFACE_DEVICE_WIDTH);
	height = s3eSurfaceGetInt(S3E_SURFACE_DEVICE_HEIGHT);
#endif
	std::string projPath = mGameMan->GetProjectPath();
	if (0!=width && 0!=height)
	{
		mWidth = width;
		mHeight = height;
	}

	mInputEventAdapter = new0 InputEventAdapter(); // input manager created in it
	mInputEventAdapter->Convert2Touch(true);

	mFontMan = new0 FontManager();
	PX2_UNUSED(mFontMan);

	mUIManager = new0 UIManager();
	mEventWorld->ComeIn(mUIManager);
	mInputEventAdapter->GetInputEventListener()->AddHandler(mUIManager->GetDefaultView());

	SoundSystemInitInfo info;
	info.MaxChannels = 24;
	info.DopplerScale = 1.0f;
	info.DistanceFactor = 100.0f;
	info.RolloffScale = 1.2f;
#if defined(_WIN32) || defined(WIN32)
	mSoundSystem = SoundSystem::Create(SoundSystem::ST_FMOD, info);
#elif defined (__ANDROID__) || defined(__MARMALADE__)
	mSoundSystem = SoundSystem::Create(SoundSystem::ST_ANDROID, info);
#endif

	mProject = new0 Project();
	mProject->SetInGamePlay(true);
	mProject->Load(projPath);
#if defined (__ANDROID__) || defined(__MARMALADE__)
	if (AST_960X640==mScreenSuitType)
	{
		mProject->SetWidth(960.0f);
		mProject->SetHeight(640.0f);
	}
	else if (AST_1136X640==mScreenSuitType)
	{
		mProject->SetWidth(1136.0f);
		mProject->SetHeight(640.0f);
	}
	else if (AST_640X960 == mScreenSuitType)
	{
		mProject->SetWidth(640.0f);
		mProject->SetHeight(960.0f);
	}
	else if (AST_640X1136 == mScreenSuitType)
	{
		mProject->SetWidth(640.0f);
		mProject->SetHeight(1136.0f);
	}
#endif
	mUIManager->GetDefaultView()->SetProjSize((float)mProject->GetWidth(), (float)mProject->GetHeight());
	Float4 color = mProject->GetColor();

	bool loadDataVersion = PX2_RM.LoadDataVersionXML("Data/version.xml");
	if (!loadDataVersion)
	{
		assertion(false, "Load Data/version.xml failed.\n");
		PX2_LOG_ERROR("Load Data/version.xml failed.");
	}

	PX2_LOG_INFO("Begin ApplicationBase::OnInitlizeApp.");
	OnInitlizeApp();
	
	mInputEventAdapter->Initlize();

	PX2_LOG_INFO("Begin ApplicationBase::OnSize.");
	OnSize(width, height);

	mScriptMan->SetUserTypePointer("PX2_LOG", "Logger", Logger::GetSingletonPtr());
	mScriptMan->SetUserTypePointer("PX2_GM", "GameManager", mGameMan);
	mScriptMan->SetUserTypePointer("PX2_PROJ", "Project", mProject);
	mScriptMan->SetUserTypePointer("PX2_LM", "LanguageManager", &(PX2_LM));
	mScriptMan->SetUserTypePointer("PX2_RM", "ResourceManager", mResMan);
	mScriptMan->SetUserTypePointer("PX2_SM", "ScriptManager", mScriptMan);
	mScriptMan->SetUserTypePointer("PX2_UIM", "UIManager", mUIManager);
	mScriptMan->SetUserTypePointer("PX2_SS", "SoundSystem", mSoundSystem);
	mScriptMan->SetUserTypePointer("PX2_SOUNDM", "SoundManager", SoundManager::GetSingletonPtr());
	
	PX2_LOG_INFO("OnInitlize()");
	OnInitlize();

	msIsInitlized = true;

	return true;
}