How to extract specific text from a webpage - web-scraping

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.

Related

Not able to map data from sql join to pydantic models in fastapi

I am trying to map data from sql join of two tables to pydantic model, but getting null value
models.py
class Countries(BaseModel):
country_name: str = Field(None, alias="country_name")
class Tools(BaseModel):
tool_name:str = Field(None, alias="tool_name")
tool_id: int = Field(None, alias="tool_id")
class ShowData(BaseModel):
countries:Countries = Field(None, alias="countries")
tools:Tools = Field(None, alias="tools")
class Config:
orm_mode = True
repository.py
def test(db: Session = Depends(get_db)):
statement = select(Tool.tool_name, UserCountryToolAccess.tool_id, Country.country_name).where(Tool.tool_id == UserCountryToolAccess.tool_id, Country.country_id == UserCountryToolAccess.country_id)
results = db.exec(statement).fetchall()
print(results)
return results
This is the data I am receiving in repository.py [('pdf compressor', 1, 'United States of America'), ('image resizer', 4, 'United Kingdom'), ('cost budgeting', 2, 'Russia'), ('scenario planner', 5, 'Germany'), ('cropping image', 1, 'United States of America'), ('leave dashboard', 3, 'Russia')]
test.py
#router.get("/test",tags=['test'],response_model=schemas.ShowData)
def get_user(db: Session = Depends(get_db)):
result = repository.test(db)
return result
I need data in the below json structure
{
"countries": {
"country_name": "India"
},
"tools": {
"tool_id": 1,
"tool_name": "pdf compressor"
}
}

Dynamically Parse Child Nodes in JSON

I have a deserialized object that I want to dynamically loop through to return the related results. The response package looks like so:
{"RatingResponse":
{"Success":"true",
"Message":"",
"QuoteID":"57451",
"LoadNum":"57451",
"Rates":
{"Rate":
[
{"SCAC":"test1",
"CarrierName":"TEST1",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"1,031.82",
"ThirdPartyCharge":"1,031.82",
"Accessorials":
{"Accessorial":
[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-952.77",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"329.04",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
},
{"SCAC":"test2",
"CarrierName":"TEST2",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"1,031.82",
"ThirdPartyCharge":"1,031.82",
"Accessorials":
{"Accessorial":
[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-952.77",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"329.04",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
}
]
},
"AverageTotalCost":"1,031.82"
}
}
I have parsed the response data so that there is less information to work with, especially since I only need the Accessorial Costs. The parsed response looks like
[
{
"SCAC": "test1",
"CarrierName": "TEST1",
"TransitTime": "1",
"ServiceLevel": "D",
"TotalCost": "1,031.82",
"ThirdPartyCharge": "1,031.82",
"Accessorials": {
"Accessorial": [
{
"Code": "400",
"Cost": "1,655.55",
"Description": "Freight"
},
{
"Code": "DSC",
"Cost": "-952.77",
"Description": "Discount"
},
{
"Code": "FUE",
"Cost": "329.04",
"Description": "Fuel Surcharge"
}
]
},
"QuoteNumber": ""
},
{
"SCAC": "test2",
"CarrierName": "TEST2",
"TransitTime": "1",
"ServiceLevel": "D",
"TotalCost": "1,031.82",
"ThirdPartyCharge": "1,031.82",
"Accessorials": {
"Accessorial": [
{
"Code": "400",
"Cost": "1,655.55",
"Description": "Freight"
},
{
"Code": "DSC",
"Cost": "-952.77",
"Description": "Discount"
},
{
"Code": "FUE",
"Cost": "329.04",
"Description": "Fuel Surcharge"
}
]
},
"QuoteNumber": ""
}
]
The problem I am facing is that I will never know how many Rate items will come back in the response data, nor will I know the exact amount of Accessorial Costs. I'm hoping to capture the Rate child node counts and the Accessorial child node counts per Rate. Here's what I have so far.
Root rootObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(responseFromServer);
//rate stores the parsed response data
JArray rate = (JArray)JObject.Parse(responseFromServer)["RatingResponse"]["Rates"]["Rate"];
var rate2 = rate.ToString();
//this for loop works as expected. it grabs the number of Rate nodes (in this example, 2)
for (int i = 0; i < rate.Count(); i++)
{
dynamic test2 = rate[i];
//this is where I'm struggling
dynamic em = (JArray)JObject.Parse(test2)["Accessorials"]["Accessorial"].Count();
for (int j = 0; j < em; j++)
{
string test3 = test2.Accessorials.Accessorial[j].Cost;
System.IO.File.AppendAllText(logPath, Environment.NewLine + test3 + Environment.NewLine);
}
}
I apologize in advance for the bad formatting and odd variable names - I'm obviously still testing the functionality, so I've been using random variables.
Where I'm struggling (as notated above) is getting to the Accessorial node to count how many items are in its array. I was thinking I could parse the first array (starting with SCAC data) and extend down to the Accessorial node, but I'm not having any luck.
Any help is GREATLY appreciated, especially since I am new to this type of code and have spent the majority of the day trying to resolve this.
you can try this
var rates = (JArray)JObject.Parse(json)["RatingResponse"]["Rates"]["Rate"];
var costs = rates.Select(r => new
{
CarrierName = r["CarrierName"],
Costs = ((JArray)((JObject)r["Accessorials"])["Accessorial"])
.Where(r => (string)r["Description"] != "Discount")
.Select(r => (double)r["Cost"]).Sum()
}).ToList();
result
[
{
"CarrierName": "TEST1",
"Costs": 1984.59
},
{
"CarrierName": "TEST2",
"Costs": 1984.59
}
]

Flask restx api model not showing model data

I have a model as follows:
class Menu(db.Model):
itemId = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(255),index=True)
price = db.Column(db.Numeric)
description = db.Column(db.String(255),index=True)
image = db.Column(db.LargeBinary)
restaurantId = db.Column(db.Integer, db.ForeignKey('restaurants.id'))
createdOn = db.Column(db.DateTime,server_default=db.func.now())
status = db.Column(db.Integer,server_default="1")
orders = db.relationship('Orders', backref='menu', lazy='dynamic')
def __repr__(self):
return '<Menu of restaurant id {}>'.format(self.restaurantId)
And I have the following api model corresponding to it:
menu_model = api.model('Menu',
{'itemId':fields.Integer(),
'name':fields.String(),
'price':fields.Float(),
'description':fields.String(),
'restaurantId':fields.Integer(),
'createdOn:':fields.DateTime(),
'status':fields.Integer()})
The problem is that even though the createdOn values are correctly generated on DB side, the response shows the createdOn field as null. What could be the reason?
"menu":
{
"itemId": 1,
"name": "Menu item",
"price": 30.0,
"description": "Menu item description",
"restaurantId": 1,
"createdOn:": null,
"status": 1
}
this will accept the desired output. The first parameter is a label, not part of the json
menus = api.model(
"menu_item",
{
'itemId':fields.Integer(),
'name':fields.String(),
'price':fields.Float(),
'description':fields.String(),
'restaurantId':fields.Integer(),
'createdOn:':fields.DateTime(),
'status':fields.Integer()
},
)
menu_model = api.model(
"Menu",
{
"menu": Nested(menus),
},
)

aws glue job to import dynamodb data

We are trying to do DynamoDB migration from prod account to stage account.
In the source account, we are making use of "Export" feature of DDB to put the compressed .json.gz files into destination S3 bucket.
We have written a glue script which will read the exported .json.gz files and writes it to DDB table.
We are making the code generic, so we should be able to migrate any DDB table from prod to stage account.
As part of that process, while testing we are facing issues when we are trying to write a NUMBER SET data to target DDB table.
Following is the sample snippet which is raising ValidationException when trying to insert into DDB
from decimal import Decimal
def number_set(datavalue):
# datavalue will be ['0', '1']
set_of_values = set()
for value in datavalue:
set_of_values.add(Decimal(value))
return set_of_values
When running the code, we are getting following ValidationException
An error occurred while calling o82.pyWriteDynamicFrame. Supplied AttributeValue is empty, must contain exactly one of the supported datatypes (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: UKEU70T0BLIKN0K2OL4RU56TGVVV4KQNSO5AEMVJF66Q9ASUAAJG; Proxy: null)
However, if instead of Decimal(value) if we use int(value) then no ValidationException is being thrown and the job succeeds.
I feel that write_dynamic_frame_from_options will try to infer schema based on the values the element contains, if the element has "int" values then the datatype would be "NS", but if the element contains all "Decimal type" values, then it is not able to infer the datatype.
The glue job we have written is
dyf = glue_context.create_dynamic_frame_from_options(
connection_type="s3",
connection_options={
"paths": [file_path]
},
format="json",
transformation_ctx = "dyf",
recurse = True,
)
def number_set(datavalue):
list_of_values = []
for value in datavalue:
list_of_values.append(Decimal(value))
print("list of values ")
print(list_of_values)
return set(list_of_values)
def parse_list(datavalue):
list_of_values = []
for object in datavalue:
list_of_values.append(generic_conversion(object))
return list_of_values
def generic_conversion(value_dict):
for datatype,datavalue in value_dict.items():
if datatype == 'N':
value = Decimal(datavalue)
elif datatype == 'S':
value = datavalue
elif datatype == 'NS':
value = number_set(datavalue)
elif datatype == 'BOOL':
value = datavalue
elif datatype == 'M':
value = construct_map(datavalue)
elif datatype == 'B':
value = datavalue.encode('ascii')
elif datatype == 'L':
value = parse_list(datavalue)
return value
def construct_map(row_dict):
ddb_row = {}
for key,value_dict in row_dict.items():
# value is a dict with key as N or S
# if N then use Decimal type
ddb_row[key] = generic_conversion(value_dict)
return ddb_row
def map_function(rec):
row_dict = rec["Item"]
return construct_map(row_dict)
mapped_dyF = Map.apply(frame = dyf, f = map_function, transformation_ctx = "mapped_dyF")
datasink2 = glue_context.write_dynamic_frame_from_options(
frame=mapped_dyF,
connection_type="dynamodb",
connection_options={
"dynamodb.region": "us-east-1",
"dynamodb.output.tableName": destination_table,
"dynamodb.throughput.write.percent": "0.5"
},
transformation_ctx = "datasink2"
)
can anyone help us in how can we unblock from this situation?
Record that we are trying to insert
{
"region": {
"S": "to_delete"
},
"date": {
"N": "20210916"
},
"number_set": {
"NS": [
"0",
"1"
]
},
"test": {
"BOOL": false
},
"map": {
"M": {
"test": {
"S": "value"
},
"test2": {
"S": "value"
},
"nestedmap": {
"M": {
"key": {
"S": "value"
},
"nestedmap1": {
"M": {
"key1": {
"N": "0"
}
}
}
}
}
}
},
"binary": {
"B": "QUFBY2Q="
},
"list": {
"L": [
{
"S": "abc"
},
{
"S": "def"
},
{
"N": "123"
},
{
"M": {
"key2": {
"S": "value2"
},
"nestedmaplist": {
"M": {
"key3": {
"S": "value3"
}
}
}
}
}
]
}
}

BFM v4.2.0 How to add DepartureDateTime

how do you add the departure date time in the request for C#? here is part of the code
refOrgDest = new BFMV430.OTA_AirLowFareSearchRQOriginDestinationInformation
{
OriginLocation = new BFMV430.OriginDestinationInformationTypeOriginLocation { LocationCode
= refItin.Origin },
DestinationLocation = new BFMV430.OriginDestinationInformationTypeDestinationLocation { LocationCode = refItin.Destination },
RPH = (i + 1).ToString(),
TPA_Extensions = new BFMV430.OTA_AirLowFareSearchRQOriginDestinationInformationTPA_Extensions
{
CabinPref = new BFMV430.CabinPrefType
{
Cabin = (BFMV430.CabinType)Enum.Parse(typeof(BFMV430.CabinType), refResBookType, true),
PreferLevel = BFMV430.PreferLevelType.Preferred,
CabinSpecified = true,
}
},
ItemElementName = BFMV430.ItemChoiceType.DepartureDateTime,
Item = new BFMV430.TravelDateTimeType
{
DepartureWindow = "00002359",
},
};
refOrgDestList.Add(refOrgDest);
also I'm getting this mismatch error when running it
Value of ItemElementName mismatches the type of System.String; you need to set it to prjWService.BFMV430.ItemChoiceType.#DepartureDateTime.
any help would be great.
thanks in advance
Here is a piece of code that could help you, the interesting part is about the date format expected by Sabre for all transaction related to search flight/availability, it means (BMF, ADVShopping, AirLowFare and etc is gonna to use the same date format). (2019-04-14T00:00:00)
__ItemOriginDestination = new AdvacedAirShopping.OTA_AirLowFareSearchRQOriginDestinationInformation
{
RPH = "1",
ItemElementName = AdvacedAirShopping.ItemChoiceType.DepartureDateTime,
Item = _FlightSearch.DepartureDateTime, //"2019-04-14T00:00:00" Here is the format expected by Sabre
OriginLocation = new AdvacedAirShopping.OriginDestinationInformationTypeOriginLocation
{
LocationCode = _FlightSearch.Origin
},
DestinationLocation = new AdvacedAirShopping.OriginDestinationInformationTypeDestinationLocation
{
LocationCode = _FlightSearch.Destination
}
};

Resources