Estimated Birth Dates

  • FH versions: V5, V6, and V7
  • Category: Dates 

The EstimatedBirthDate() function usually produces a sensible Date, but some scenarios produce an erratic Date, and this Plugin function attempts to correct such errors. (The errors have been reported to Calico Pie.)

Usually if the Birth Event has a Date then that overrides any estimated Date, but not always.

Some of the scenarios that cause erratic estimates are:

  • The first Fact with a Date and Age overrides all other Facts (except a Birth Event with Date) even if there is a lifetime Fact with a Date earlier than that estimated Date.
  • If such a Fact has a Before Date then that becomes the EARLIEST estimated Date, which is often later than the LATEST estimated Date, and even if a Birth Event has an earlier Before Date.
  • If a Death Event has a Before Date without an Age then that becomes the LATEST estimated Date, even if there is a lifetime Fact with a Date earlier than that estimated Date, unless it is a key fact such as a Birth, Baptism, Christening, or Marriage.

Requires: Code Snippet Get Day Number


-- Make EstimatedBirthDate EARLIEST <= LATEST <= 1st Fact Date --
function EstimatedBirthDates(ptrIndi,intGens)
  intGens = intGens or 2
  local dateMin = fhCallBuiltInFunction("EstimatedBirthDate",ptrIndi,"EARLIEST",intGens)
  local dateMax = fhCallBuiltInFunction("EstimatedBirthDate",ptrIndi,"LATEST",intGens)
  local dateMid = fhNewDatePt()
  if not ( dateMin:IsNull() or dateMax:IsNull() ) then
    local ptrFact = fhNewItemPtr()
    while ptrFact:IsNotNull() do				-- Find 1st Fact with a Date
      if fhIsFact(ptrFact) then
        local datFact = fhGetValueAsDate(fhGetItemPtr(ptrFact,"~.DATE"))
        if not datFact:IsNull() then
          local datLast = datFact:GetDatePt1()	-- Last date = DatePt1 for Simple, Range, and Before
          local strType = datFact:GetSubtype()	-- Between = DatePt2 and After = DatePt1 + 10yrs
          if   strType == "Between" then datLast = datFact:GetDatePt2()
          elseif strType == "After" then datLast:SetValue(datLast:GetYear()+10,datLast:GetMonth(),datLast:GetDay(),datLast:GetYearDD()) end
          if dateMax:Compare(datLast) > 0 then dateMax = datLast end
          if dateMin:Compare(dateMax) > 0 then dateMin = dateMax end
          if strType ~= "After" then break end	-- Now EARLIEST <= LATEST <= Last date
    local intDays = ( GetDayNumber(dateMax) - GetDayNumber(dateMin) ) / 2
    local intYear,remYear = math.modf( intDays / 365.2422 )	-- Offset year @ 365.2422 days per year, and remainder fraction
    local intMnth = math.floor( remYear * 12 )		-- Offset month is remainder fraction of year * 12
    dateMid = fhCallBuiltInFunction("CalcDate",dateMin,intYear,intMnth)
  return { Min=dateMin; Mid=dateMid; Max=dateMax; }		-- Return EARLIEST, MID, LATEST dates
end -- function EstimatedBirthDates


Preferably, the function should use the first post-birth fact, but the Normal Time Frame setting is not available to Plugins.

The user can circumvent such erratic estimates by setting a Between Dates period for the Birth Event however approximate that may be.


local arrBirthDate = EstimatedBirthDates(ptrIndi,9)
local datEarliest  = arrBirthDate.Min -- fhCallBuiltInFunction("EstimatedBirthDate",ptrIndi,"EARLIEST",9)
local datMiddle    = arrBirthDate.Mid -- fhCallBuiltInFunction("EstimatedBirthDate",ptrIndi,"MID",9)
local datLatest    = arrBirthDate.Max -- fhCallBuiltInFunction("EstimatedBirthDate",ptrIndi,"LATEST",9)


Last update: 16 Dec 2020