diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl
index fd366abce096f32624e59b06446c93bc68e081b5..606ebc478ecad982421ba6d38cdbbd0218251cb0 100644
--- a/src/nature/species/skylark.jl
+++ b/src/nature/species/skylark.jl
@@ -52,7 +52,8 @@ At the moment, this implementation is still in development.
     const maxforagecover = 0.7 # maximum preferred vegetation cover for foraging
     const nestingheight = (15cm, 25cm) # min and max preferred vegetation height for nesting
     const nestingcover = (0.2, 0.5) # min and max preferred vegetation cover for nesting
-    
+
+    const matefaithfulness = 0.5 # chance of a female retaining her previous partner
     const nestingbegin::Tuple{Int64,Int64} = (April, 10) # begin nesting in the middle of April
     const nestbuildingtime::UnitRange{Int64} = 4:5 # 4-5 days needed to build a nest (doubled for first nest)
     const eggsperclutch::UnitRange{Int64} = 2:5 # eggs laid per clutch
@@ -85,16 +86,13 @@ Non-breeding adults move around with other individuals and check for migration.
         @follow(@rand(neighbours), 30m) #XXX magic number
     # check if the bird migrates
     leave, arrive = self.migrationdates
-    month, day = monthday(model.date)
-    migrate = (((month < arrive[1]) || (month == arrive[1] && day < arrive[2])) ||
-               ((month > leave[1]) || (month == leave[1] && day >= leave[2])))
-    if migrate
+    if leave <= model.date < arrive
         @kill(self.migrationmortality, "migration")
-        returndate = Date(year(model.date)+1, arrive[1], arrive[2])
         self.sex == male ?
             @setphase(territorysearch) :
             @setphase(matesearch)
-        @migrate(returndate)
+        @migrate(arrive)
+        self.migrationdates = self.migrationdates .+ Year(1)
     end
 end
 
@@ -136,22 +134,35 @@ end
 Females returning from migration move around to look for a suitable partner with a territory.
 """
 @phase Skylark matesearch begin
-    #TODO move around, looking for a male with an established territory
-    #TODO teilweise Partnertreue
-
+    if self.mate != -1 # if the female already had a partner last year...
+        if isalive(@animal(self.mate))
+            if @chance(self.matefaithfulness)
+                # ...check if he is still alive and the female wants to stay with him
+                #XXX is mate-faithfulness decided by the female when she returns,
+                # or by the male taking whichever female comes to him first?
+                @debug "$(animalid(self)) and $(animalid(n)) have mated again."
+                @setphase(nesting)
+                return
+            else
+                self.mate = -1
+                @animal(self.mate).mate = -1
+            end
+        else
+            self.mate = -1
+        end
+    end
     # look for a mate among the neighbouring birds, or move randomly
     for n in @neighbours(self.visionrange)
         if n.sex == male && n.mate == -1 && n.phase == occupation
-            self.mate = n.id
+            self.mate = n.id  #XXX may be the old partner again by chance
             n.mate = self.id
+            @setphase(nesting)
             @debug "$(animalid(self)) and $(animalid(n)) have mated."
-            break
+            return
         end
     end
     #@debug("$(animalid(self)) didn't find a mate.")
-    if self.mate != -1
-        @setphase(nesting)
-    elseif month(model.date) > self.nestingend # stop trying to find a mate if it's too late
+    if month(model.date) > self.nestingend # stop trying to find a mate if it's too late
         @setphase(nonbreeding)
     else
         @walk("random", self.movementrange)
@@ -225,8 +236,8 @@ function migrationdates(skylark::Skylark, model::SimulationModel)
     minarrive = skylark.sex == male ? (February, 15) : (March, 1)
     deltaleave = @rand(0:45) #XXX ought to be normally distributed
     deltaarrive = @rand(0:15) #XXX ought to be normally distributed
-    leave = monthday(Date(2001, minleave[1], minleave[2]) + Day(deltaleave))
-    arrive = monthday(Date(2001, minarrive[1], minarrive[2]) + Day(deltaarrive))
+    leave = Date(year(model.date), minleave[1], minleave[2]) + Day(deltaleave))
+    arrive = Date(year(model.date)+1, minarrive[1], minarrive[2]) + Day(deltaarrive))
     (leave, arrive)
 end
 
@@ -266,13 +277,11 @@ function findterritory(skylark::Skylark, model::SimulationModel)
         for c in coords # ...then inspect them
             (c[1] <= 0 || c[2] <= 0 || c[1] > msize[1] || c[2] > msize[2]) && continue
             (isoccupied(model, "Skylark", c)) && continue
+            push!(territory, c)
             quality = foragequality(skylark, model, c)
+            effectivesize += @param(world.mapresolution)^2*quality
+            (quality > 0) && (constrained = false)
             #XXX check for nesting habitats?
-            if quality > 0
-                constrained = false
-                push!(territory, c)
-                effectivesize += @param(world.mapresolution)^2*quality
-            end
         end
         radius +=1
     end
@@ -329,18 +338,14 @@ should currently be on migration. Also sets other individual-specific variables.
 """
 @create Skylark begin
     @debug "Added $(animalid(self)) at $(self.pos)"
-    self.migrationdates = migrationdates(self, model) #XXX should be dynamic
+    self.migrationdates = migrationdates(self, model) .- Year(1) #XXX should be dynamic
     leave, arrive = self.migrationdates
-    mon, day = monthday(model.date)
-    migrate = (((mon < arrive[1]) || (mon == arrive[1] && day < arrive[2])) ||
-               ((mon > leave[1]) || (mon == leave[1] && day >= leave[2])))
-    if migrate
-        returndate = Date(year(model.date), arrive[1], arrive[2])
-        model.date != @param(core.startdate) && (returndate += Year(1))
+    if leave <= model.date < arrive
         self.sex == male ?
             @setphase(territorysearch) :
             @setphase(matesearch)
-        @migrate(returndate)
+        @migrate(arrive)
+        self.migrationdates = self.migrationdates .+ Year(1))
     end
 end