/// <summary>
        /// Return the human-friendly textual description of the sschedule pattern
        /// </summary>
        /// <returns></returns>
        public string GetTextualDescription()
        {
            StringBuilder sb = new StringBuilder();

            // daily pattern
            if (Times != null && Times.Count() > 0)
            {
                sb.Append("at ");
                bool fst = false;
                Times.ForEach(x => { sb.Append(string.Format("{0}{1}", fst ? ", " : " ", x.ToString())); fst = true; });
            }
            else
            {
                if (StartTime > startTimeDefault)
                {
                    sb.Append(string.Format("from {0} ", StartTime.ToString()));
                }
                if (StopTime < stopTimeDefault)
                {
                    sb.Append(string.Format("to {0} ", StopTime.ToString()));
                }
                if (DailyInterval > 0 && (DailyFrequency == RecurrenceFrequency.Secondly || DailyFrequency == RecurrenceFrequency.Minutely || DailyFrequency == RecurrenceFrequency.Hourly))
                {
                    sb.Append(string.Format(" every {0} {1}", DailyInterval.ToString(), DailyFrequency == RecurrenceFrequency.Hourly ? "hours" : (DailyFrequency == RecurrenceFrequency.Minutely ? "minutes" : "seconds")));
                }
            }

            // day/week/month pattern

            return(sb.ToString());
        }
        public override List <Error> Validate(List <Error> errors)
        {
            RequireString(this, x => x.TaskID, 14, errors, "A");
            ValidateString(this, x => x.TaskDesignator, 32, errors, "B");
            ValidateString(this, x => x.CustomerIdRef, 14, errors, "C");
            ValidateString(this, x => x.FarmIdRef, 14, errors, "D");
            ValidateString(this, x => x.PartFieldIdRef, 14, errors, "E");
            ValidateString(this, x => x.ResponsibleWorkerIdRef, 14, errors, "F");
            ValidateEnumerationValue(typeof(ISOTaskStatus), TaskStatusInt, errors);
            if (DefaultTreatmentZoneCode.HasValue)
            {
                ValidateRange(this, x => x.DefaultTreatmentZoneCode.Value, 0, 254, errors, "H");
            }
            if (PositionLostTreatmentZoneCode.HasValue)
            {
                ValidateRange(this, x => x.PositionLostTreatmentZoneCode.Value, 0, 254, errors, "I");
            }
            if (OutOfFieldTreatmentZoneCode.HasValue)
            {
                ValidateRange(this, x => x.OutOfFieldTreatmentZoneCode.Value, 0, 254, errors, "J");
            }
            TreatmentZones.ForEach(i => i.Validate(errors));
            Times.ForEach(i => i.Validate(errors));
            if (OperationTechPractice != null)
            {
                OperationTechPractice.Validate(errors);
            }
            WorkerAllocations.ForEach(i => i.Validate(errors));
            DeviceAllocations.ForEach(i => i.Validate(errors));
            Connections.ForEach(i => i.Validate(errors));
            ProductAllocations.ForEach(i => i.Validate(errors));
            DataLogTriggers.ForEach(i => i.Validate(errors));
            CommentAllocations.ForEach(i => i.Validate(errors));
            TimeLogs.ForEach(i => i.Validate(errors));
            if (Grid != null)
            {
                Grid.Validate(errors);
            }
            GuidanceAllocations.ForEach(i => i.Validate(errors));

            return(errors);
        }