code: func NewCronExpr(expr string) (cronExpr *CronExpr, err error) {
  	fields := strings.Fields(expr)
  	if len(fields) != 5 && len(fields) != 6 {
  		err = fmt.Errorf("invalid expr %v: expected 5 or 6 fields, got %v", expr, len(fields))
  		return
  	}
  
  	if len(fields) == 5 {
  		fields = append([]string{"0"}, fields...)
  	}
  
  	cronExpr = new(CronExpr)
  	// Seconds
  	cronExpr.sec, err = parseCronField(fields[0], 0, 59)
  	if err != nil {
  		goto onError
  	}
  	// Minutes
  	cronExpr.min, err = parseCronField(fields[1], 0, 59)
  	if err != nil {
  		goto onError
  	}
  	// Hours
  	cronExpr.hour, err = parseCronField(fields[2], 0, 23)
  	if err != nil {
  		goto onError
  	}
  	// Day of month
  	cronExpr.dom, err = parseCronField(fields[3], 1, 31)
  	if err != nil {
  		goto onError
  	}
  	// Month
  	cronExpr.month, err = parseCronField(fields[4], 1, 12)
  	if err != nil {
  		goto onError
  	}
  	// Day of week
  	cronExpr.dow, err = parseCronField(fields[5], 0, 6)
  	if err != nil {
  		goto onError
  	}
  	return
  
  onError:
  	err = fmt.Errorf("invalid expr %v: %v", expr, err)
  	return
  }
docs: // goroutine safe