diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
index 677e7fc0..1f1310cf 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
@@ -32,12 +32,16 @@ import android.view.inputmethod.EditorInfo;
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.m2049r.xmrwallet.util.RestoreHeight;
 import com.m2049r.xmrwallet.widget.Toolbar;
 import com.m2049r.xmrwallet.model.Wallet;
 import com.m2049r.xmrwallet.model.WalletManager;
 import com.m2049r.xmrwallet.util.Helper;
 
 import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
 
 import timber.log.Timber;
 
@@ -231,9 +235,7 @@ public class GenerateFragment extends Fragment {
         }
         if (!type.equals(TYPE_NEW)) {
             etWalletRestoreHeight.setVisibility(View.VISIBLE);
-            etWalletRestoreHeight.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener()
-
-            {
+            etWalletRestoreHeight.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
                 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                     if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
                         Helper.hideKeyboard(getActivity());
@@ -281,6 +283,42 @@ public class GenerateFragment extends Fragment {
         return ok;
     }
 
+    private boolean checkHeight() {
+        long height = !type.equals(TYPE_NEW) ? getHeight() : 0;
+        boolean ok = true;
+        if (height < 0) {
+            etWalletRestoreHeight.setError(getString(R.string.generate_restoreheight_error));
+            ok = false;
+        }
+        if (ok) {
+            etWalletRestoreHeight.setError(null);
+        }
+        return ok;
+    }
+
+    private long getHeight() {
+        long height = 0;
+
+        String restoreHeight = etWalletRestoreHeight.getEditText().getText().toString().trim();
+        if (restoreHeight.isEmpty()) return -1;
+        try {
+            // is it a date?
+            SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
+            parser.setLenient(false);
+            parser.parse(restoreHeight);
+            height = RestoreHeight.getInstance().getHeight(restoreHeight);
+        } catch (ParseException exPE) {
+            try {
+                // or is it a height?
+                height = Long.parseLong(restoreHeight);
+            } catch (NumberFormatException exNFE) {
+                return -1;
+            }
+        }
+        Timber.d("Using Restore Height = %d", height);
+        return height;
+    }
+
     private boolean checkMnemonic() {
         String seed = etWalletMnemonic.getEditText().getText().toString();
         boolean ok = (seed.split("\\s").length == 25); // 25 words
@@ -327,15 +365,13 @@ public class GenerateFragment extends Fragment {
 
     private void generateWallet() {
         if (!checkName()) return;
+        if (!checkHeight()) return;
+
         String name = etWalletName.getEditText().getText().toString();
         String password = etWalletPassword.getEditText().getText().toString();
 
-        long height;
-        try {
-            height = Long.parseLong(etWalletRestoreHeight.getEditText().getText().toString());
-        } catch (NumberFormatException ex) {
-            height = 0; // Keep calm and carry on!
-        }
+        long height = getHeight();
+        if (height < 0) height = 0;
 
         if (type.equals(TYPE_NEW)) {
             bGenerate.setEnabled(false);
diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/RestoreHeight.java b/app/src/main/java/com/m2049r/xmrwallet/util/RestoreHeight.java
new file mode 100644
index 00000000..29b1c537
--- /dev/null
+++ b/app/src/main/java/com/m2049r/xmrwallet/util/RestoreHeight.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2018 m2049r
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.m2049r.xmrwallet.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+
+public class RestoreHeight {
+    static private RestoreHeight Singleton = null;
+
+    static public RestoreHeight getInstance() {
+        if (Singleton == null) {
+            synchronized (RestoreHeight.class) {
+                if (Singleton == null) {
+                    Singleton = new RestoreHeight();
+                }
+            }
+        }
+        return Singleton;
+    }
+
+    private Map<String, Long> blockheight = new HashMap<>();
+
+    RestoreHeight() {
+        blockheight.put("2014-05-01", 18844L);
+        blockheight.put("2014-06-01", 65406L);
+        blockheight.put("2014-07-01", 108882L);
+        blockheight.put("2014-08-01", 153594L);
+        blockheight.put("2014-09-01", 198072L);
+        blockheight.put("2014-10-01", 241088L);
+        blockheight.put("2014-11-01", 285305L);
+        blockheight.put("2014-12-01", 328069L);
+        blockheight.put("2015-01-01", 372369L);
+        blockheight.put("2015-02-01", 416505L);
+        blockheight.put("2015-03-01", 456631L);
+        blockheight.put("2015-04-01", 501084L);
+        blockheight.put("2015-05-01", 543973L);
+        blockheight.put("2015-06-01", 588326L);
+        blockheight.put("2015-07-01", 631187L);
+        blockheight.put("2015-08-01", 675484L);
+        blockheight.put("2015-09-01", 719725L);
+        blockheight.put("2015-10-01", 762463L);
+        blockheight.put("2015-11-01", 806528L);
+        blockheight.put("2015-12-01", 849041L);
+        blockheight.put("2016-01-01", 892866L);
+        blockheight.put("2016-02-01", 936736L);
+        blockheight.put("2016-03-01", 977691L);
+        blockheight.put("2016-04-01", 1015848L);
+        blockheight.put("2016-05-01", 1037417L);
+        blockheight.put("2016-06-01", 1059651L);
+        blockheight.put("2016-07-01", 1081269L);
+        blockheight.put("2016-08-01", 1103630L);
+        blockheight.put("2016-09-01", 1125983L);
+        blockheight.put("2016-10-01", 1147617L);
+        blockheight.put("2016-11-01", 1169779L);
+        blockheight.put("2016-12-01", 1191402L);
+        blockheight.put("2017-01-01", 1213861L);
+        blockheight.put("2017-02-01", 1236197L);
+        blockheight.put("2017-03-01", 1256358L);
+        blockheight.put("2017-04-01", 1278622L);
+        blockheight.put("2017-05-01", 1300239L);
+        blockheight.put("2017-06-01", 1322564L);
+        blockheight.put("2017-07-01", 1344225L);
+        blockheight.put("2017-08-01", 1366664L);
+        blockheight.put("2017-09-01", 1389113L);
+        blockheight.put("2017-10-01", 1410738L);
+        blockheight.put("2017-11-01", 1433039L);
+        blockheight.put("2017-12-01", 1454639L);
+        blockheight.put("2018-01-01", 1477201L);
+        blockheight.put("2018-02-01", 1499599L);
+    }
+
+    public long getHeight(String date) {
+        SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
+        parser.setTimeZone(TimeZone.getTimeZone("UTC"));
+        parser.setLenient(false);
+        try {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+            cal.set(Calendar.DST_OFFSET, 0);
+            cal.setTime(parser.parse(date));
+            cal.add(Calendar.DAY_OF_MONTH, -4); // give it some leeway
+            if (cal.get(Calendar.YEAR) < 2014)
+                return 1;
+            if ((cal.get(Calendar.YEAR) == 2014) && (cal.get(Calendar.MONTH) <= 3))
+                // before May 2014
+                return 1;
+
+            Calendar query = (Calendar) cal.clone();
+
+            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+            cal.set(Calendar.DAY_OF_MONTH, 1);
+            long prevTime = cal.getTimeInMillis();
+            String prevDate = formatter.format(prevTime);
+            // lookup blockheight at first of the month
+            Long prevBc = blockheight.get(prevDate);
+            if (prevBc == null) {
+                // if too recent, go back in time and find latest one we have
+                while (prevBc == null) {
+                    cal.add(Calendar.MONTH, -1);
+                    if (cal.get(Calendar.YEAR) < 2014) {
+                        throw new IllegalStateException("endless loop looking for blockheight");
+                    }
+                    prevTime = cal.getTimeInMillis();
+                    prevDate = formatter.format(prevTime);
+                    prevBc = blockheight.get(prevDate);
+                }
+            }
+            long height = prevBc;
+            // now we have a blockheight & a date ON or BEFORE the restore date requested
+            if (date.equals(prevDate)) return height;
+            // see if we have a blockheight after this date
+            cal.add(Calendar.MONTH, 1);
+            long nextTime = cal.getTimeInMillis();
+            String nextDate = formatter.format(nextTime);
+            Long nextBc = blockheight.get(nextDate);
+            if (nextBc != null) { // we have a range - interpolate the blockheight we are looking for
+                long diff = nextBc - prevBc;
+                long diffDays = TimeUnit.DAYS.convert(nextTime - prevTime, TimeUnit.MILLISECONDS);
+                long days = TimeUnit.DAYS.convert(query.getTimeInMillis() - prevTime,
+                        TimeUnit.MILLISECONDS);
+                height = Math.round(prevBc + diff * (1.0 * days / diffDays));
+            } else {
+                long days = TimeUnit.DAYS.convert(query.getTimeInMillis() - prevTime,
+                        TimeUnit.MILLISECONDS);
+                height = Math.round(prevBc + 1.0 * days * (24 * 60 / 2));
+            }
+            return height;
+        } catch (ParseException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+}
diff --git a/app/src/main/res/layout/fragment_generate.xml b/app/src/main/res/layout/fragment_generate.xml
index 27b0a0db..517ba60c 100644
--- a/app/src/main/res/layout/fragment_generate.xml
+++ b/app/src/main/res/layout/fragment_generate.xml
@@ -144,7 +144,7 @@
                 android:layout_height="wrap_content"
                 android:hint="@string/generate_restoreheight_hint"
                 android:imeOptions="actionDone"
-                android:inputType="number"
+                android:inputType="date"
                 android:textAlignment="textStart" />
         </android.support.design.widget.TextInputLayout>
 
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index cd426221..ce523337 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -142,6 +142,8 @@
     <string name="generate_wallet_created">Monedero creada</string>
     <string name="generate_wallet_create_failed">Creación de monedero fallida</string>
 
+    <string name="generate_restoreheight_error">Introduce un número o una fecha (AAAA-MM-DD)</string>
+
     <string name="generate_wallet_type_key">Claves</string>
     <string name="generate_wallet_type_new">Nuevo</string>
     <string name="generate_wallet_type_seed">Semilla</string>
@@ -151,7 +153,7 @@
     <string name="generate_viewkey_hint">Clave de Vista</string>
     <string name="generate_spendkey_hint">Clave de Gasto</string>
     <string name="generate_mnemonic_hint">Semilla Mnemotécnica de 25 Palabras</string>
-    <string name="generate_restoreheight_hint">Altura de Restauración</string>
+    <string name="generate_restoreheight_hint">Altura o Fecha (YYYY-MM-DD) de Restauración</string>
 
     <string name="generate_wallet_label">Monedero</string>
     <string name="generate_password_label">Contraseña</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c9514d54..fd4e8191 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -213,6 +213,8 @@
     <string name="generate_wallet_created">Wallet created</string>
     <string name="generate_wallet_create_failed">Wallet create failed</string>
 
+    <string name="generate_restoreheight_error">Enter Number or Date (YYYY-MM-DD)</string>
+
     <string name="generate_wallet_type_key">Keys</string>
     <string name="generate_wallet_type_new">New</string>
     <string name="generate_wallet_type_seed">Seed</string>
@@ -222,7 +224,7 @@
     <string name="generate_viewkey_hint">View Key</string>
     <string name="generate_spendkey_hint">Spend Key</string>
     <string name="generate_mnemonic_hint">25-Word Mnemonic Seed</string>
-    <string name="generate_restoreheight_hint">Restore Height</string>
+    <string name="generate_restoreheight_hint">Restore Height or Date (YYYY-MM-DD)</string>
 
     <string name="generate_wallet_label">Wallet</string>
     <string name="generate_password_label">Password</string>
diff --git a/app/src/test/java/com/m2049r/xmrwallet/util/RestoreHeightTest.java b/app/src/test/java/com/m2049r/xmrwallet/util/RestoreHeightTest.java
new file mode 100644
index 00000000..620b06eb
--- /dev/null
+++ b/app/src/test/java/com/m2049r/xmrwallet/util/RestoreHeightTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017 m2049r
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.m2049r.xmrwallet.util;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertTrue;
+
+// all ranges go back 5 days
+
+public class RestoreHeightTest {
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Test
+    public void pre2014() {
+        assertTrue(getHeight("2013-12-01") == 1);
+        assertTrue(getHeight("1958-12-01") == 1);
+    }
+
+    @Test
+    public void zero() {
+        assertTrue(getHeight("2014-04-27") == 1);
+    }
+
+    @Test
+    public void notZero() {
+        assertTrue(getHeight("2014-05-07") > 1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void notDateA() {
+        getHeight("2013-13-04");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void notDateB() {
+        getHeight("2013-13-01-");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void notDateC() {
+        getHeight("x013-13-01");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void notDateD() {
+        getHeight("2013-12-41");
+    }
+
+    @Test
+    public void test201709() {
+        // getHeight() returns blockheight of < two days ago
+        assertTrue(isInRange(getHeight("2017-09-01"), 1383957, 1387716));
+        assertTrue(isInRange(getHeight("2017-09-05"), 1386967, 1390583));
+        assertTrue(isInRange(getHeight("2017-09-21"), 1398492, 1402068));
+    }
+
+    @Test
+    public void test20160324() { // blocktime changed from 1 minute to 2 minutes on this day
+        assertTrue(isInRange(getHeight("2016-03-23"), 998955, 1006105));
+        assertTrue(isInRange(getHeight("2016-03-24"), 1000414, 1007486));
+        assertTrue(isInRange(getHeight("2016-03-25"), 1001800, 1008900));
+        assertTrue(isInRange(getHeight("2016-03-26"), 1003243, 1009985));
+        assertTrue(isInRange(getHeight("2016-03-27"), 1004694, 1010746));
+    }
+
+    @Test
+    public void test2014() {
+        assertTrue(isInRange(getHeight("2014-04-26"), 1, 8501));
+        assertTrue(isInRange(getHeight("2014-05-09"), 20289, 28311));
+        assertTrue(isInRange(getHeight("2014-05-17"), 32608, 40075));
+        assertTrue(isInRange(getHeight("2014-05-30"), 52139, 59548));
+    }
+
+    @Test
+    public void test2015() {
+        assertTrue(isInRange(getHeight("2015-01-26"), 397914, 405055));
+        assertTrue(isInRange(getHeight("2015-08-13"), 682595, 689748));
+    }
+
+    @Test
+    public void test2016() {
+        assertTrue(isInRange(getHeight("2016-01-26"), 918313, 925424));
+        assertTrue(isInRange(getHeight("2016-08-13"), 1107244, 1110793));
+    }
+
+    @Test
+    public void test2017() {
+        assertTrue(isInRange(getHeight("2017-01-26"), 1226806, 1230402));
+        assertTrue(isInRange(getHeight("2017-08-13"), 1370264, 1373854));
+        assertTrue(isInRange(getHeight("2017-08-31"), 1383254, 1386967));
+        assertTrue(isInRange(getHeight("2017-06-09"), 1323288, 1326884));
+    }
+
+    @Test
+    public void post201802() {
+        assertTrue(isInRange(getHeight("2018-02-19"), 1507579, 1511127));
+    }
+
+    @Test
+    public void postFuture() {
+        long b_20180208 = 1504715;
+        long b_20180808 = b_20180208 + 720 * (28 + 31 + 30 + 31 + 30 + 31);
+        assertTrue(isInRange(getHeight("2018-08-08"), b_20180808 - 720 * 5, b_20180808));
+    }
+
+
+    private boolean isInRange(long n, long min, long max) {
+        if (n > max) return false;
+        if (n < min) return false;
+        return true;
+    }
+
+    private long getHeight(String date) {
+        return RestoreHeight.getInstance().getHeight(date);
+    }
+}