That usually happens due to Daylight Saving Time (DST) (also known as "summer time"). Based on the date/time, and on the output you've got (Sun Oct 16 01:00:00 BRST 2016), I suppose it's Brazil's DST (BRST is the abbreviation for Brazilian's summer time).
SimpleDateFormat uses the JVM's default timezone (if you don't specify one), so probably your default zone is America/Sao_Paulo or Brazil/East (you can check that by calling TimeZone.getDefault().getID()).
In America/Sao_Paulo timezone, DST started at October 16th 2016: at midnight, clocks shifted 1 hour forward from midnight to 1 AM (and the offset changed from -03:00 to -02:00). So all local times between 00:00 and 00:59 didn't exist in this timezone (you can also think that clocks changed from 23:59:59.999999999 directly to 01:00).
That's why this specific date in midnight (which didn't exist in this timezone) is automatically shifted to the next valid moment (1 AM). But if I set a specific timezone in the formatter, this won't happen:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// set formatter to use UTC (instead of JVM default timezone)
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// parse it as midnight (no shift to 01:00)
Date date = sdf.parse("2016-10-16 00:00:00");
In this case, I'm using UTC, which has no DST effects. But remind that the date created above will be equivalent to midnight in UTC (which is the same instant as October 15th 2016 at 9 PM in Brazil (the day before) - maybe it's not what you want).
Be aware of that before changing the timezone: if you want a specific instant (a precise point in time), changing the timezone will affect the final result. If you just want to consider the date/time values and don't care about in what timezone it is (treating the value as it's a "local date/time"), just set the formatter to use UTC, to avoid DST effects (an ugly workaround, IMO, but just because the java.util.Date API doesn't have specific types for local date/times).
But anyway, this is not an error. It's the expected behaviour (DST and timezones have lots of strange and non-intuitive behaviours, but that's the way it is).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java 6 or 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
This new API has lots of new types that best suit different use-cases. In your case, if you want just the date and time fields and don't care about timezones, you can use a LocalDateTime. To parse it, just use a DateTimeFormatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dt = LocalDateTime.parse("2016-10-16 00:00:00", fmt);
System.out.println(dt); // 2016-10-16T00:00
This will ignore DST effects, because a LocalDateTime has no timezone information.
But if you want to consider the timezone, you can convert this to a ZonedDateTime, using a ZoneId to get the timezone:
// convert to a timezone
ZonedDateTime z = dt.atZone(ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2016-10-16T01:00-02:00[America/Sao_Paulo]
In this case, note that the time was adjusted to 1 AM, because I converted to America/Sao_Paulo timezone, so the DST effects were considered, as already explained above.
With this new API we can look closer at what's happening in this specific timezone, for this particular date/time. First I'll create a ZonedDateTime that corresponds to October 15th 2016, at 23:59:59 in America/Sao_Paulo timezone, and then I'll add 1 second to it:
// October 15th 2016, at 23:59:59 in Sao Paulo timezone
ZonedDateTime z = ZonedDateTime.of(2016, 10, 15, 23, 59, 59, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2016-10-15T23:59:59-03:00[America/Sao_Paulo]
System.out.println(z.plusSeconds(1)); // 2016-10-16T01:00-02:00[America/Sao_Paulo]
Note that the original date is in offset -03:00 (3 hours behind UTC, which is the standard offset for America/Sao_Paulo timezone). One second later, it should be midnight, but due to DST change, the clock shifts directly to 1 AM, and the offset changes to -02:00.
Even if I try to directly create October 16th 2016 at midnight in this timezone, the value will be corrected, because this local time doesn't exist in this timezone, due to DST shift:
// Try to create October 16th 2016, at midnight in Sao Paulo timezone
ZonedDateTime z = ZonedDateTime.of(2016, 10, 16, 0, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2016-10-16T01:00-02:00[America/Sao_Paulo]
So, it's not an error. October 16th 2016 at midnight in America/Sao_Paulo timezone doesn't exist due to a DST change, and the API's automatically corrects this to the next valid moment (which is, in this case, 1 AM).
The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
You can also use the system's default timezone with ZoneId.systemDefault(), but this can be changed without notice, even at runtime, so it's better to explicity use a specific one.