// Copy constructor public CPGDate( CPGDate date ) { m_etType = date.m_etType; m_ecCalendar = date.m_ecCalendar; if( date.m_year != null ) m_year = new CYear( date.m_year ); else m_year = null; m_uMonth = date.m_uMonth; m_uDay = date.m_uDay; if( date.m_yearTo != null ) m_yearTo = new CYear( date.m_yearTo ); else m_yearTo = null; m_uMonthTo = date.m_uMonthTo; m_uDayTo = date.m_uDayTo; m_sPhrase = date.m_sPhrase; }
// Used for guesses made from parent's death year public CListableYear( CPGDate date, bool bBefore ) { if( date != null ) { m_date = new CPGDate( date ); if( bBefore ) { m_date.m_etType = CPGDate.EType.RangeBefore; base.Text = String.Concat("prob bef ", date.Year ); } else { m_date.m_etType = CPGDate.EType.RangeAfter; base.Text = String.Concat("prob aft ", date.Year ); } } else { m_date = null; } }
// Parse a GEDCOM Julian date string and create an appropriate CPGDate object. // Returns null if parsing failed. // First tries day month year, then month year, then year. private static CPGDate ParseDateJuln( ref string sDate ) { string sTemp = sDate; uint uDay=0, uMonth=0; CYear year = null; uDay = ParseDay( ref sTemp ); if( uDay > 0 ) { uMonth = ParseMonth( ref sTemp ); if( uMonth > 0 ) { year = ParseYear( ref sTemp ); if( year != null ) { CPGDate date = new CPGDate(); date.m_uDay = uDay; date.m_uMonth = uMonth; date.m_year = year; date.m_etType = EType.Single; date.m_ecCalendar = ECalendar.Julian; sDate = sTemp; return date; } } } sTemp = sDate; uDay = 0; uMonth = ParseMonth( ref sTemp ); if( uMonth > 0 ) { year = ParseYear( ref sTemp ); if( year != null ) { CPGDate date = new CPGDate(); date.m_uDay = uDay; date.m_uMonth = uMonth; date.m_year = year; date.m_etType = EType.Single; date.m_ecCalendar = ECalendar.Julian; sDate = sTemp; return date; } } sTemp = sDate; uDay = 0; uMonth = 0; year = ParseYear( ref sTemp ); if( year != null ) { CPGDate date = new CPGDate(); date.m_uDay = uDay; date.m_uMonth = uMonth; date.m_year = year; date.m_etType = EType.Single; date.m_ecCalendar = ECalendar.Julian; sDate = sTemp; return date; } return null; }
// Used by comparison functions to ensure that a range has a valid lower bound, by setting the earliest date possible. private static void AssertLower( ref CPGDate date ) { if( !IsValid( date ) ) { date = new CPGDate(); date.m_etType = CPGDate.EType.Single; date.m_uDay = 1; date.m_uMonth = 1; date.m_year = new CYear(1); } }
// Used by comparison functions to ensure that a range has a valid upper bound, by setting the latest date possible (i.e. today). private static void AssertHigher( ref CPGDate date ) { if( !IsValid( date ) ) { DateTime dtNow = DateTime.Now; date = new CPGDate(); date.m_etType = CPGDate.EType.Single; date.m_uDay = (uint)dtNow.Day; date.m_uMonth = (uint)dtNow.Month; date.m_year = new CYear(dtNow.Year); } }
// Returns duration of the date in days, for periods and ranges. Returns 1 for single dates etc. // TODO: only returns approximate duration, doesn't account for leap years, days in month, different calendars, alternate years etc. public uint GetDuration( CPGDate lowerLimit, CPGDate upperLimit ) { AssertLower( ref lowerLimit ); AssertHigher( ref upperLimit ); switch( m_etType ) { case EType.PeriodFrom: case EType.RangeAfter: return (uint)Math.Abs(CountDays( m_uDay, m_uMonth, m_year.m_nYear, upperLimit.m_uDay, upperLimit.m_uMonth, upperLimit.m_year.m_nYear )); case EType.PeriodTo: case EType.RangeBefore: return (uint)Math.Abs(CountDays( lowerLimit.m_uDay, lowerLimit.m_uMonth, lowerLimit.m_year.m_nYear, m_uDay, m_uMonth, m_year.m_nYear )); case EType.PeriodFromTo: case EType.RangeBetween: return (uint)Math.Abs(CountDays( m_uDay, m_uMonth, m_year.m_nYear, m_uDayTo, m_uMonthTo, m_yearTo.m_nYear )); case EType.Single: case EType.ApproximatedAbout: case EType.ApproximatedCalculated: case EType.ApproximatedEstimate: case EType.Interpreted: case EType.Phrase: default: return 1; } }
// Returns true if the specified date falls inside the range of this date instance. private bool Encompasses( CPGDate date ) { if (date == null) { return false; } switch( m_etType ) { case EType.PeriodFrom: case EType.RangeAfter: return date.IsAfter( m_uDay, m_uMonth, m_year.m_nYear ); case EType.PeriodTo: case EType.RangeBefore: return date.IsBefore( m_uDay, m_uMonth, m_year.m_nYear ); case EType.PeriodFromTo: case EType.RangeBetween: return date.IsBefore( m_uDayTo, m_uMonthTo, m_yearTo.m_nYear ) && date.IsAfter( m_uDay, m_uMonth, m_year.m_nYear ); case EType.Single: case EType.ApproximatedAbout: case EType.ApproximatedCalculated: case EType.ApproximatedEstimate: case EType.Interpreted: case EType.Phrase: default: return date.Encompasses( m_uDay, m_uMonth, m_year.m_nYear ); } }
// Returns true if this instance contains valid date information. public static bool IsValid( CPGDate date ) { return( date != null && date.m_year != null ); }
// Returns the number of days difference between the two given dates, or 0 if the date ranges overlap. public static int Difference( CPGDate date1, CPGDate date2 ) { AssertLower( ref date1 ); AssertHigher( ref date2 ); // If date2 encompasses date1, difference = 0 if (date2.Encompasses(date1)) { return 0; } // If date1 encompasses date2, difference = 0 if (date1.Encompasses(date2)) { return 0; } return CountDays( date1.m_uDay, date1.m_uMonth, date1.m_year.m_nYear, date2.m_uDay, date2.m_uMonth, date2.m_year.m_nYear ); }
// Parse a GEDCOM date phrase string and create an appropriate CPGDate object. // Returns null if parsing failed. private static CPGDate ParseDatePhrase( ref string sDate ) { string sTemp = sDate; CPGDate date = null; CGedcom.ParseWhitespace( ref sTemp ); if( sTemp != null && sTemp != "" ) { date = new CPGDate(); date.m_sPhrase = sTemp; date.m_etType = EType.Phrase; sDate = ""; } return date; }
// Event handler // Excludes people who aren't dead, but leave people we're not sure about private void pruneIndividualsContextMenuAlive_Click(Object sender, System.EventArgs e) { Cursor.Current = Cursors.WaitCursor; Cursor.Show(); m_nPruneExcluded = 0; m_nPruneIncluded = 0; CPGDate dateNow = new CPGDate(DateTime.Now); CPGDate dateThen = new CPGDate(DateTime.Now); dateThen.m_year.m_nYear -= 100; try { m_gedcom.BeginPruning(); foreach (ListViewItem lvi in m_listviewPruneRecordsIndis.Items) { if (lvi is CListableBool) { LLClasses.CIndividualRecord ir = (LLClasses.CIndividualRecord)((CListableBool)lvi).ISRecord; if (ir != null) { CPGDate dateBorn = null; CPGQualifiedDate qualdateBorn = ir.BirthDate; if (qualdateBorn != null) { dateBorn = qualdateBorn.m_date; } CPGDate dateDied = null; CPGQualifiedDate qualdateDied = ir.DeathDate; if (qualdateDied != null) { dateDied = qualdateDied.m_date; } bool bInclude = true; if (ir.Living) { bInclude = false; } else if (IsAlive(dateBorn, dateDied, dateNow, dateThen)) { bInclude = false; } if (bInclude == false && !ir.Restricted) { m_nPruneExcluded++; ir.Restricted = true; } } } } m_gedcom.EndPruning(); } catch (System.Exception ex) { ReportPruneError(ex); } // Rebuild list FillIndividualsList(m_listviewPruneRecordsIndis, false, null, true); Cursor.Current = Cursors.Default; Cursor.Hide(); ShowPruneResult(m_nPruneExcluded, m_nPruneIncluded, "individual"); }
// Helper function. Compares dates to see if we know this person is alive private static bool IsAlive(CPGDate dateBorn, CPGDate dateDied, CPGDate dateNow, CPGDate dateThen) { if (dateDied != null) { if (dateDied.CompareTo(dateNow) > 0) { // Have to have death date after today return true; } } else if (dateBorn != null && dateBorn.CompareTo(dateThen) > 0) { // Have to be born after dateThen return true; } return false; }
// Constructor public CPGQualifiedDate( CPGDate date, EQualification qualification ) { m_date = date; m_eqQualification = qualification; }
// Constructor public CListableYear( CPGDate date ) { m_date = date; base.Text = ToString(); }