Search code examples
javaapigsonstrava

Strava API v3 - 'GET all athlete activities' - how can I calculate the' before' and 'after' for a certain point in time?


I am writing a java program to fetch all of my activities from the 01/01/2020 until the current date.

My problem is that Strava requires an integer, as you can see in the picture below, for the 'before' and 'after' part of the request. Since no further information is given on their website on what the value of those two variables is based on, I do not know what to put there.

Here is the imageof the description of the Strava API I mentioned, and the Link to it as well:

https://developers.strava.com/docs/reference/#api-Activities-getLoggedInAthleteActivities

That is my otherwise working code which just needs the right values to be done:

public List<AthleteActivities> getAthleteActivities(long before, long after, int page, int per_page,
            String access_token) {
        System.out.println(access_token);
        List<AthleteActivities> aa = new ArrayList<AthleteActivities>();
        Type listType = new TypeToken<List<AthleteActivities>>() {
        }.getType();

        try {
            while (true) {
                String link = "https://www.strava.com/api/v3/athlete/activities?before=" + before + "&after=" + after
                        + "&page=" + page + "&per_page=" + per_page;
                URL url = new URL(link);

                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.setRequestProperty("Content-Type", "application/json; utf-8");
                con.setRequestProperty("Accept", "application/json");
                con.setRequestProperty("Authorization", "Bearer " + access_token);
                con.setDoOutput(true);
                
                Reader reader = new InputStreamReader(con.getInputStream(), "UTF-8");
                Gson gson = new Gson();

                List<AthleteActivities> temp = gson.fromJson(reader, listType);
                if (temp.size() == 0) {
                    return aa;
                }

                aa.addAll(temp);
                page++;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
        // return null;

    }

I used Gson to save the returned .json we get from the inquiry in this class:

import com.google.gson.annotations.SerializedName;

public class AthleteActivities {
    @SerializedName("resource_state")
    private double resource_state;
    @SerializedName("name")
    private String name;
    @SerializedName("distance")
    private double distance;
    @SerializedName("moving_time")
    private double moving_time;
    @SerializedName("elapsed_time")
    private double elapsed_time;
    @SerializedName("total_elevation_gain")
    private double total_elevation_gain;
    @SerializedName("type")
    private String type;
    @SerializedName("id")
    private double id;
    @SerializedName("external_id")
    private String external_id;
    @SerializedName("upload_id")
    private double upload_id;
    @SerializedName("start_date")
    private String start_date;
    @SerializedName("start_date_local")
    private String start_date_local;
    @SerializedName("timezone")
    private String timezone;
    @SerializedName("utc_offset")
    private double utc_offset;
    @SerializedName("average_speed")
    private double average_speed;
    @SerializedName("max_speed")
    private double max_speed;
    @SerializedName("average_cadence")
    private double average_cadence;
    @SerializedName("average_watts")
    private double average_watts;
    @SerializedName("weighted_average_watts")
    private double weighted_average_watts;
    @SerializedName("kilojoules")
    private double kilojoules;
    @SerializedName("device_watts")
    private boolean device_watts;
    @SerializedName("has_heartrate")
    private boolean has_heartrate;
    @SerializedName("average_heartrate")
    private double average_heartrate;
    @SerializedName("max_heartrate")
    private double max_heartrate;
    @SerializedName("max_watts")
    private double max_watts;
    @SerializedName("pr_count")
    private double pr_count;
    @SerializedName("total_photo_count")
    private double total_photo_count;
    @SerializedName("elev_high")
    private double elev_high;
    @SerializedName("elev_low")
    private double elev_low;
    @SerializedName("has_kudoed")
    private boolean has_kudoed;
    @SerializedName("suffer_score")
    private double suffer_score;

    public double getResource_state() {
        return resource_state;
    }

    public String getName() {
        return name;
    }

    public double getDistance() {
        return distance;
    }

    public double getMoving_time() {
        return moving_time;
    }

    public double getElapsed_time() {
        return elapsed_time;
    }

    public double getTotal_elevation_gain() {
        return total_elevation_gain;
    }

    public String getType() {
        return type;
    }

    public double getId() {
        return id;
    }

    public String getExternal_id() {
        return external_id;
    }

    public double getUpload_id() {
        return upload_id;
    }

    public String getStart_date() {
        return start_date;
    }

    public String getStart_date_local() {
        return start_date_local;
    }

    public String getTimezone() {
        return timezone;
    }

    public double getUtc_offset() {
        return utc_offset;
    }

    public double getAverage_speed() {
        return average_speed;
    }

    public double getMax_speed() {
        return max_speed;
    }

    public double getAverage_cadence() {
        return average_cadence;
    }

    public double getAverage_watts() {
        return average_watts;
    }

    public double getWeighted_average_watts() {
        return weighted_average_watts;
    }

    public double getKilojoules() {
        return kilojoules;
    }

    public boolean isDevice_watts() {
        return device_watts;
    }

    public boolean isHas_heartrate() {
        return has_heartrate;
    }

    public double getAverage_heartrate() {
        return average_heartrate;
    }

    public double getMax_heartrate() {
        return max_heartrate;
    }

    public double getMax_watts() {
        return max_watts;
    }

    public double getPr_count() {
        return pr_count;
    }

    public double getTotal_photo_count() {
        return total_photo_count;
    }

    public double getElev_high() {
        return elev_high;
    }

    public double getElev_low() {
        return elev_low;
    }

    public boolean isHas_kudoed() {
        return has_kudoed;
    }

    public double getSuffer_score() {
        return suffer_score;
    }

}


I would really appreciate any help as to how I can calculate those integer values to represent the time I require for my request.

If you need further information please let me know via commenting.


Solution

  • As stated in the API docs, before and after are epoch timestamps (the number of seconds since 1 January 1970, a common way to represent a point in time).

    You can use an Epoch Converter to convert a human-readable timestamp to an epoch timestamp, or preferrably, use Java date/time classes:

    //1 January 2020 00:00:00 UTC
    OffsetDateTime after = OffsetDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
    getAthleteActivities(..., after.toEpochSecond(), ...);
    

    In case you need a local timezone instead of UTC:

    //1 January 2020 00:00:00 CET
    ZonedDateTime after = ZonedDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneId.of("Europe/Vienna"));
    getAthleteActivities(..., after.toEpochSecond(), ...);