I am interested in finding patterns of constellations. I am using 'Sky map' android app for visual inspection, now I want to build an app to find similar constellation structures. A sub-problem of that is to find the coordinates for specific celestial objects.
Example: How can I obtain the coordinates of 'Moon' at a given time,date and location.
https://theskylive.com/planetarium provides this information on their webpage in following manner.
Object: Moon [info|live][less]
Right Asc: 04h 15m 12.5s **Decl: 17° 05' 46.3"** (J2000) [HMS|Dec]
Magnitude: -10.54 Altitude: 56° Solar Elongation: 100.4° Constellation: Ari
Sun distance: 147.77 Million Km Earth distance: 0.38 Million Km
Rise: 10:48 Transit: 18:40 Set: 01:35 **Europe/London**
For Moon we can find coordinates using the webpage, Is there some API? or How can we do it by extracting coordinate information from the web page.
I am not an Android expert, but this is what you can do in
build.gradle
plugins {
id 'java'
}
group 'test.test'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
implementation 'com.squareup.okhttp3:okhttp:3.13.1'
compile group: 'org.json', name: 'json', version: '20180813'
}
Planetarium.java
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONObject;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Planetarium {
OkHttpClient client = new OkHttpClient();
JSONObject get(String... objects) throws IOException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
StringBuilder urlBuilder = new StringBuilder("https://theskylive.com/planetariumdata?");
// Current date in YYYY-MM-DD format
urlBuilder.append("date=").append(dateFormat.format(new Date()));
// add url query string for all objects
for (String obj : objects) {
// URL encoded aobj[] => aobj%5B%5D=
urlBuilder.append("&").append("aobj%5B%5D=").append(obj);
}
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
try (Response response = client.newCall(request).execute()) {
String json = response.body().string();
return new JSONObject(json);
}
}
public static void main(String[] args) throws IOException {
Planetarium planetarium = new Planetarium();
JSONObject response = planetarium.get("moon", "mars");
System.out.println(response.toString(2));
}
}
OUTPUT:
{
"utc_seconds": 1551816600,
"utc_timestamp": "201903052010",
"objects": {
"moon": {
"distsun": 1.479847408587E8,
"altitude": -32.421642244539,
"dec": -12.501182812768,
"constell": "Cap",
"timezone": "Europe/London",
"hlat": "-0.0075",
"hlong": "163.9072",
"elongation": "9.6",
"lastdate": "2019-Mar-05 00:00",
"hx": -0.95427043393163,
"hy": 0.26061067578779,
"mag": "-4.82",
"hlongRad": 2.8607203077248,
"hz": -1.6343451194632E-4,
"utc_time": 1551816600,
"distearth": 405722.20937018,
"sot": 350.29647638889,
"id": "moon",
"circumstances": {
"transit_local": 11.428494722983,
"raise_ut": 1.5517668981849E9,
"set": 16.623858118962,
"raise_local": 6.3606069281934,
"visibility": "partial",
"azimuth_set": 256.90380469917,
"LSTs": 3.4997935653561,
"LSTr": 17.208442522882,
"set_local": 16.623858118962,
"azimuth_rise": 104.50312047906,
"GSTs": 3.4997935653561,
"GSTr": 17.208442522882,
"transit_ut": 1.551785142581E9,
"transit": 11.428494722983,
"raise": 6.3606069281934,
"set_ut": 1.5518038458892E9,
"transit_height": 24.710020581601
},
"ar": 22.578738425926,
"name": "Moon",
"category": "planets",
"hlatRad": -1.3089969389957E-4,
"age": 27,
"status": true
},
"mars": {
"distsun": 2.2963710671492E8,
"altitude": 27.808183248664,
"circumstances": {
"transit_local": 15.80120694427,
"raise_ut": 1.5517741680418E9,
"set": 23.222402283833,
"raise_local": 8.3800116047075,
"visibility": "partial",
"azimuth_set": 286.34760861411,
"LSTs": 10.11640394619,
"LSTr": 19.233376146402,
"set_local": 23.222402283833,
"azimuth_rise": 73.652391385888,
"GSTs": 10.11640394619,
"GSTr": 19.233376146402,
"transit_ut": 1.551800884345E9,
"transit": 15.80120694427,
"raise": 8.3800116047075,
"set_ut": 1.5518276006482E9,
"transit_height": 54.867608614112
},
"dec": 16.347608614112,
"constell": "Ari",
"timezone": "Europe/London",
"hlat": "0.8142",
"hlong": "75.6345",
"elongation": "58.1",
"lastdate": "2019-Mar-05 00:00",
"hx": 0.36958631955143,
"ar": 2.6748900462963,
"hy": 1.4897081109635,
"mag": "1.23",
"hlongRad": 1.3200710530997,
"hz": 0.022145899657793,
"utc_time": 1551816600,
"distearth": 2.704192732295E8,
"name": "Mars",
"sot": 58.1002,
"id": "mars",
"category": "planets",
"hlatRad": 0.014210470769738,
"status": true
},
"sun": {
"distsun": 0,
"altitude": -22.992657046501,
"circumstances": {
"transit_local": 12.176106019167,
"raise_ut": 1.551767861711E9,
"set": 17.739026911053,
"raise_local": 6.6282530456618,
"visibility": "partial",
"azimuth_set": 263.93596334029,
"LSTs": 4.618015588543,
"LSTr": 17.476821431166,
"set_local": 17.739026911053,
"azimuth_rise": 96.242086753282,
"GSTs": 4.618015588543,
"GSTr": 17.476821431166,
"transit_ut": 1.5517878339817E9,
"transit": 12.176106019167,
"raise": 6.6282530456618,
"set_ut": 1.5518078604969E9,
"transit_height": 32.366908597329
},
"dec": -6.0242450863769,
"constell": "Aqr",
"timezone": "Europe/London",
"hlat": "n.a.",
"hlong": "n.a.",
"elongation": 0,
"lastdate": "2019-Mar-05 00:00",
"hx": 0,
"ar": 23.060617283951,
"hy": 0,
"mag": "-26.76",
"hlongRad": null,
"hz": 0,
"utc_time": 1551816600,
"distearth": 1.4838474994878E8,
"name": "Sun",
"sot": 0,
"id": "sun",
"category": "planets",
"hlatRad": null,
"status": true
}
},
"target": "sun"
}
I'm not sure if this is helpful, but here is a python implementation to it. You'd have to figure out the accepted location parameters, but date, hour, and minute are all there:
import requests
url = 'https://theskylive.com/planetariumdata'
params = {
'obj': 'moon',
'h': '10',
'm': '30',
'date': '2019-02-28',
'localdata': '51.48|0|Greenwich, United Kingdom|Europe/London'}
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'}
response = requests.get(url, params=params, headers=headers).json()
print (response['objects']['moon'])
Output:
{'status': True, 'utc_time': 1551349800, 'ar': 18.114288194444, 'dec': -21.301003146701, 'mag': '-9.11', 'distsun': 148031243.76562, 'distearth': 399053.81054688, 'constell': 'Oph', 'sot': 292.2907375, 'lastdate': '2019-Feb-28 00:00', 'hlong': '158.9866', 'hlongRad': 2.7748396365512, 'hlat': '0.0060', 'hlatRad': 0.00010471975511966, 'hx': -0.92639216172362, 'hy': 0.34779595586615, 'hz': 8.4403227939488e-05, 'elongation': '67.7', 'altitude': 7.7566655880485, 'id': 'moon', 'name': 'Moon', 'category': 'planets', 'circumstances': {'visibility': 'partial', 'raise': 3.0419974882059, 'set': 11.875359660362, 'transit': 7.4771821984014, 'raise_ut': 1551322951.191, 'set_ut': 1551354751.2948, 'transit_ut': 1551338917.8559, 'transit_height': 17.341269275926, 'azimuth_rise': 110.98610232928, 'azimuth_set': 248.66063774998, 'LSTr': 13.552197907652, 'LSTs': 22.409745024956, 'GSTr': 13.552197907652, 'GSTs': 22.409745024956, 'raise_local': 3.0419974882059, 'set_local': 11.875359660362, 'transit_local': 7.4771821984014}, 'timezone': 'Europe/London', 'age': 23}
Below you can find the code on how to do this in python. There are numerous ways to incorporate the code in an app. Just for illustration I casted the results in a pandas dataframe so you could view the results. I also added some code to deal with proxy settings, if this is not so, you could leave it out and simply get the url text with the requests package.
Hope it helps.
import urllib
import pandas as pd
import numpy as np
username = 'userID' # ex. ID
password = "password!" # password
dataURL = "https://theskylive.com/moon-info"
proxies = {
'https': 'https://{}:{}#proxy:port'.format(username, password)}
proxy = urllib.request.ProxyHandler(proxies)
opener = urllib.request.build_opener(proxy)
urllib.request.install_opener(opener)
with urllib.request.urlopen(dataURL) as url:
text = str(url.read())
tableStart = text.find('The Moon Ephemeris')
tableEnd = text.find('Distance of The Moon from Earth')
tableProgress = tableStart
findSTR = 'moon&date='
loc = text.find(findSTR,tableStart,tableEnd)
startDate = text[loc+len(findSTR):loc+len(findSTR)+10]
table = []
tableRow = []
counter = 0
counter2 = 0
diff = [20,4]
while loc>0:
loc1 = text.find('<td class="desktop">',tableProgress,tableEnd)
loc2 = text.find('<td>',tableProgress,tableEnd)
if loc1<0:
if loc2<0:
loc = -1
else:
loc = loc2
pos = 1
else:
if loc2<0:
loc = loc1
pos = 0
else:
loc = np.min([loc1,loc2])
pos = np.argmin([loc1,loc2])
if loc>0:
locStart = loc+diff[pos]
loc = text.find('</td>',loc,tableEnd)
if loc>0:
extractedText = text[locStart:loc]
if counter ==1:
extractedText = extractedText.replace('°',' deg')
extractedText = extractedText.replace('’',' min')
extractedText = extractedText.replace('”',' sec')
elif counter ==3:
extractedText = extractedText.replace('”',' arcsec')
tableRow = tableRow+ [extractedText]
tableProgress = loc
counter = counter+1
if counter==5:
counter2 = counter2+1
counter = 0
table = table+[tableRow]
tableRow = []
idx = pd.date_range(start='2019-02-26', periods=len(table), freq='D')
cols = ['Right Ascension','Declination','Magnitude','Apparent Diameter','Constellation']
Data = pd.DataFrame(table,index=idx,columns=cols)
print(Data)
Just instead setting up your own data scraping server you could use IFTTT for getting the data and storeing it at first.
Here are some nice tutorials: https://public.tableau.com/en-us/s/blog/2013/08/data-scraping-part-i-ifttt
Im sure you don't want your app to do the scraping.
After you got it stored you can further manipulate it with whatever language and provide it in e.g. json format as a cacheable datasource for your app.
Can't seem to get unix timestamps working with moment.js...
date_create is equal to my php unix timestamp in this case and I want to use that as the startDate, minDate, and a few other places... I am not getting an error, but it is displaying as 'December 31, 1969 # 7:00 pm' which is obviously not correct.
What am I doing wrong here? The goal is to have the correct date/time shown as computers time from the utc timestamp given.
For instance 1401079499 is 05 / 26 / 14 # 4:44:59am UTC, but this would show as May 26, 2014 12:44:59 am on my own computer being gmt-4
var date_create = $('#dashboard-report-range #date-display').html(); //equals 1401079499
//date range stuff
$('#dashboard-report-range').daterangepicker({
opens: 'left',
startDate: moment.unix(date_create).startOf('day'),
endDate: moment().endOf('day'),
minDate: moment.unix(date_create).startOf('day'),
maxDate: moment().endOf('day'),
showDropdowns: false,
showWeekNumbers: true,
timePicker: true,
timePickerIncrement: 1,
timePicker12Hour: true,
ranges: {
'All': [moment.unix(date_create).startOf('day'), moment().endOf('day')],
'Today': [moment().startOf('day'), moment().endOf('day')],
'Yesterday': [moment().subtract('days', 1).startOf('day'), moment().subtract('days', 1).endOf('day')],
'Last 7 Days': [moment().subtract('days', 6).startOf('day'), moment().endOf('day')],
'Last 30 Days': [moment().subtract('days', 29).startOf('day'), moment().endOf('day')],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
},
buttonClasses: ['btn'],
applyClass: 'btn-sm btn-success',
cancelClass: 'btn-sm btn-default',
format: 'MM/DD/YYYY',
//format: 'MM-DD-YY',
separator: ' to ',
locale: {
applyLabel: 'Apply',
fromLabel: 'From',
toLabel: 'To',
customRangeLabel: 'Custom Range',
daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
firstDay: 1
}
},
function (start, end) {
$('#dashboard-report-range #date-display').html('<span class="ddate_start">' + start.format('MMMM D, YYYY [#] h:mm a') + '</span> <i class="fa fa-arrows-h"></i> <span class="ddate_end">' + end.format('MMMM D, YYYY [#] h:mm a') + '</span>');
$('#dashboard-report-range #date-start').html( start.unix() );
$('#dashboard-report-range #date-end').html( end.unix() );
dt.draw();
}
);
$('#dashboard-report-range #date-display').html('<span class="ddate_start">' + moment.unix(date_create).startOf('day').format('MMMM D, YYYY [#] h:mm a') + '</span> <i class="fa fa-arrows-h"></i> <span class="ddate_end">' + moment().endOf('day').format('MMMM D, YYYY [#] h:mm a') + '</span>');
$('#dashboard-report-range').show();
};
EDIT - solution :
I had forgotten to change the id I grab the unix timestamp from... $('#dashboard-report-range #date-create').html(); With that change everything works as it should.
Multiply the timestamp by 1000.
PHP returns timestamp in seconds, but JS understands it as milliseconds.
I am using fullcalendar plugin to get and display holidays of a month via Ajax. The problem I am having, is that the method that retrieves the holidays accepts only a year and a month as parameter, not a date range.
When using month view of fullcalendar, the start and end parameter ranges from feb 23rd and Apr 6th. I need it to range from Mar 1st to Mar 31st. That way, I can only get year and month part to call the method.
This is what I tried but without success:
$('#calendar').fullCalendar({
monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
monthNamesShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
dayNamesShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
events: '/get_month_holidays',
start: {
month: new Date((new Date()).getFullYear(), (new Date()).getMonth(), 1)
},
end: {
month: (new Date((new Date()).getFullYear(), (new Date()).getMonth() + 1, 1)) - 1
},
buttonText: {
today: 'hoy'
}
})
Any help will be appreciated,
Thanks
Jaime
Finally I used:
eventSources: [
{
url: '/get_month_holidays',
type: 'POST',
data: function() {
var fecha = $('#calendar').fullCalendar('getDate');
return {
month: fecha.getMonth() + 1,
year: fecha.getFullYear()
}
}
}
],
And it worked. Thanks anyway.
Jaime
jstuardo's solution adds new parameters to the request so you end up with something like this:
http://your.api.com/events?month=8&year=2015&start=2015-07-27&end=2015-09-07
Which is quite confusing and requires you to change the API accordingly.
Better solution would be to change the default start and end parameters. You can achieve that using something like this:
{
url: baseUrl + '/events',
startParam: null, //resetting default fullcalendar parameter
endParam: null, //resetting default fullcalendar parameter
data: function() {
var date = $('#gc-calendar').fullCalendar('getDate')._d;
var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
firstDay = $filter('date')(firstDay, 'yyyy-MM-dd');
lastDay = $filter('date')(lastDay, 'yyyy-MM-dd');
//AngularJS way of changing the date format to yyyy-mm-dd
return {
start: firstDay,
end: lastDay
}
}
}
This way your request looks like this:
http://your.api.com/calendar_orders?start=2015-08-01&end=2015-08-31
You can format the date to 'yyy-MM-dd' using any method you like. You can find a bunch of them here:
Get String in YYYYMMDD format from JS date object?
I am trying to set the time format in my calendar rows to appear as 1pm - 2pm, 2pm - 3pm, 3pm- 4pm, etc.
I have tried the following:
agenda: 'h:mm{ - h:mm}',
axisFormat: 'h:mm{ - h:mm}',
day: 'h:mm{ - h:mm}',
axisFormat: 'h(:mm)tt',
timeFormat: {
agenda: 'h:mm{ - h:mm}'
},
but none of the above, either alone or in combination seem to work for me.
I initialize my calendar as below:
$('#calendar').fullCalendar({
defaultView: 'agendaDay',
allDaySlot: false,
firstHour: 9,
minTime: 9,
maxTime: 19,
selectable: true,
unselectAuto: true,
slotMinutes: 60,
weekends: false,
year: current_year,
month: current_month,
date: current_day,
columnFormat: '',
FullCalendar does not provide a "to" time for the axisFormat and therefore the { - h:mm} part of you axisFormat is ignored.
And I don't think there's any way to do it without editing the FullCalendar source code.
But if you are feeling adventurous you could do the following changes in fullcalendar.js around line 3207:
d = zeroDate();
maxd = addMinutes(cloneDate(d), maxMinute);
addMinutes(d, minMinute);
// Add two lines
var toD = cloneDate(d);
addMinutes(toD, opt('slotMinutes'));
slotCnt = 0;
for (i=0; d < maxd; i++) {
minutes = d.getMinutes();
s +=
"<tr class='fc-slot" + i + ' ' + (!minutes ? '' : 'fc-minor') + "'>" +
"<th class='fc-agenda-axis " + headerClass + "'>" +
// Changed line from "formatDate(d, opt('axisFormat')...)" to "formatDates(d, toD, opt('axisFormat')...)"
((!slotNormal || !minutes) ? formatDates(d, toD, opt('axisFormat')) : ' ') +
"</th>" +
"<td class='" + contentClass + "'>" +
"<div style='position:relative'> </div>" +
"</td>" +
"</tr>";
addMinutes(d, opt('slotMinutes'));
// Add line
addMinutes(toD, opt('slotMinutes'));
slotCnt++;
}