Repository: go-co-op/gocron (Go)

Issue:
[BUG] - Incorrect nextRun with Weekday(), StartAt() and At()
### Describe the bug

Incorrect nextRun() when i set StartAt

### To Reproduce
Current time for example: 2022-11-18 20:19:00 +0000 UTC

**First example:**

When i set StartAt future date, i got wrong nextRun (date from _time variable)
```
s2 := gocron.NewScheduler(time.UTC)
s2.StartAsync()
_time, _ := time.Parse("2006-01-02 15:04:05", "2022-11-21 16:29:55")
s2.Every(1).Friday().At("20:19").StartAt(_time).Do(func() {})
fmt.Println(s2.NextRun())
```

Output:
2022-11-21 16:29:55 +0000 UTC

**Second example:**

When i set StartAt past date, i got wrong nextRun (date from current time)
```
s2 := gocron.NewScheduler(time.UTC)
s2.StartAsync()
_time, _ := time.Parse("2006-01-02 15:04:05", "2022-11-10 16:29:55")
s2.Every(1).Friday().At("20:19").StartAt(_time).Do(func() {})
fmt.Println(s2.NextRun())
```

Output:
2022-11-18 20:19:00 +0000 UTC

### Version

v1.18.0

### Expected behavior

**First example:**
2022-11-25 20:19:00 +0000 UTC

**Second example:**
2022-11-11 20:19:00 +0000 UTC



Discussion:

Patch:
diff --git a/scheduler.go b/scheduler.go
index 06770a31..a05d854b 100644
--- a/scheduler.go
+++ b/scheduler.go
@@ -217,7 +217,7 @@ func (s *Scheduler) scheduleNextRun(job *Job) (bool, nextRun) {
 // durationToNextRun calculate how much time to the next run, depending on unit
 func (s *Scheduler) durationToNextRun(lastRun time.Time, job *Job) nextRun {
 	// job can be scheduled with .StartAt()
-	if job.getStartAtTime().After(lastRun) {
+	if job.getFirstAtTime() == 0 && job.getStartAtTime().After(lastRun) {
 		return nextRun{duration: job.getStartAtTime().Sub(s.now()), dateTime: job.getStartAtTime()}
 	}
 
@@ -233,6 +233,9 @@ func (s *Scheduler) durationToNextRun(lastRun time.Time, job *Job) nextRun {
 		} else {
 			next = s.calculateWeeks(job, lastRun)
 		}
+		if next.dateTime.Before(job.getStartAtTime()) {
+			return s.durationToNextRun(job.getStartAtTime(), job)
+		}
 	case months:
 		next = s.calculateMonths(job, lastRun)
 	case duration:


Test patch:
diff --git a/scheduler_test.go b/scheduler_test.go
index bbfef750..c9b99a67 100644
--- a/scheduler_test.go
+++ b/scheduler_test.go
@@ -996,6 +996,44 @@ func TestScheduler_StartAt(t *testing.T) {
 		assert.Equal(t, now.Add(10*time.Minute).Truncate(time.Second), job.NextRun().Truncate(time.Second))
 		s.stop()
 	})
+
+	t.Run("StartAt() in future with Weekday() and At()", func(t *testing.T) {
+		ft := fakeTime{onNow: func(l *time.Location) time.Time {
+			// 1/1/1970 is a Thursday
+			return time.Date(1970, 1, 1, 12, 0, 0, 0, l)
+		}}
+
+		s := NewScheduler(time.UTC)
+		s.time = ft
+
+		dt := time.Date(1970, 1, 10, 0, 0, 0, 0, time.UTC)
+		job, err := s.Every(1).Friday().At("20:19").StartAt(dt).Do(func() {})
+		require.NoError(t, err)
+
+		s.StartAsync()
+		exp := time.Date(1970, 1, 16, 20, 19, 0, 0, time.UTC)
+		assert.Equal(t, exp, job.NextRun())
+		s.Stop()
+	})
+
+	t.Run("StartAt() in the past with Weekday() and At()", func(t *testing.T) {
+		ft := fakeTime{onNow: func(l *time.Location) time.Time {
+			// 1/1/1971 is a Friday
+			return time.Date(1971, 1, 1, 12, 0, 0, 0, l)
+		}}
+
+		s := NewScheduler(time.UTC)
+		s.time = ft
+
+		dt := time.Date(1970, 12, 3, 0, 0, 0, 0, time.UTC)
+		job, err := s.Every(1).Thursday().At("20:19").StartAt(dt).Do(func() {})
+		require.NoError(t, err)
+
+		s.StartAsync()
+		exp := time.Date(1971, 1, 7, 20, 19, 0, 0, time.UTC)
+		assert.Equal(t, exp, job.NextRun())
+		s.Stop()
+	})
 }
 
 func TestScheduler_CalculateNextRun(t *testing.T) {
@@ -1943,7 +1981,8 @@ func TestScheduler_WaitForSchedules(t *testing.T) {
 
 	counterMutex.RLock()
 	defer counterMutex.RUnlock()
-	assert.Equal(t, 2, counter)
+	assert.GreaterOrEqual(t, counter, 2)
+	assert.LessOrEqual(t, counter, 3)
 }
 
 func TestScheduler_LenWeekDays(t *testing.T) {