Error while formatting the date variables in sas - format

I am getting an error when i try to do format for a date variable.
This is how my date variable values look-like "26-Dec-58"
"The format $DATE was not found or could not be loaded"
The reason for the error is that my date value is stored as a char variable in the data set so its not accepting the format of a numeric variable when i am formatting the variable.
So i want to convert my date (which is a character) variable into a numeric variable without introducing a new variable.
I tried datepart and substring options but still getting error.
I am still at the learning stage in sas so any code to clear the error is appreciated i know the concept but coding i tried with all i know but still no luck.
Current code:
data Practice.Sales;
set Practice.Sales;
Birthdate = '26-Dec-58';
Purchase_Dt = '15-Sep-04';
t_num_date = input(Birthdate, ddmmyy8.);
t_num_date1 = input(Purchase_Dt, ddmmyy8.);
drop Birthdate Purchase_Dt;
format Birth_date ddmmyy8. PurchaseDt ddmmyy8. Price DOLLAR10.2;
rename t_num_date = Birthdate;
rename t_num_date1 = Purchase_Dt;
run;

It isn't possible to change an existing variable in a SAS dataset directly from character to numeric. However, you can create a new numeric variable, drop the original character variable, then rename the new one:
data example;
mydate = '26-Dec-58';
t_num_date = input(mydate, date9.);
drop mydate;
format t_num_date date9.;
rename t_num_date = mydate;
output;
run;
N.B. you have to apply the format to the temporary variable before it gets renamed. Attempting to apply a numeric format after renaming it results in an error, as the format statement is processed before the rest of the data step runs, and at that point the original character variable hasn't been dropped yet.

This code works fine for me but still the newly created variables are coming at the last how to change that
data Practice.Sales;
set Practice.Sales;
Birth_date=datepart(input(Birthdate,anydtdtm19.));
PurchaseDt = datepart(input(Purchase_Dt,anydtdtm19.));
format Birth_date PurchaseDt ddmmyy8. Price DOLLAR10.2;
drop Birthdate Purchase_Dt;
run;

You need to use the rename at set statement and then drop them at the end.
data Practice.Sales;
set Practice.Sales
*rename old variables;
(rename=(birthdate=birth_date purchase_dt=purchasedt));
*use renamed variables in code;
Birthdate=datepart(input(Birth_date,anydtdtm19.));
Purchase_Dt = datepart(input(PurchaseDt,anydtdtm19.));
format Birthdate Purchase_Dt date9. Price DOLLAR10.2;
drop Birth_date PurchaseDt;
run;

The variables in a SAS dataset appear in the order they were created.
If you really want to determine the order of the variables yourself, then you should create them before your set statement. Further, I suppose you prefer NOT changing the name of the variables, while still changing their type. Therefore we have to rename the existing variables while reading them.
data Practice.Sales;
format Birthdate Purchase_Dt ddmmyy8. Price DOLLAR10.2;
set Practice.Sales (rename =(Birthdate=oldBirth Purchase_Dt = oldPurchase));
Birthdate=datepart(input(oldBirth,anydtdtm19.));
Purchase_Dt = datepart(input(oldPurchase,anydtdtm19.));
drop Birthdate Purchase_Dt;
run;

Related

Date conversion in SAS (String to Date)

I import an Excel-spreadsheet using the following SAS-procedure.
%let datafile = 'Excel.xlsx'
%let tablename = myDB
proc import datafile = &datafile
out = &tablename
dbms = xlsx
replace
;
run;
One of the variables (date_variable) has the format DD.MM.YYYY. Therefore, I was defining a new format like this:
data &tablename;
set &tablename;
format date_variable mmddyy10.;
run;
Now, I would like to sort the table by that variable:
proc sort data = &tablename;
by date_variable;
run;
However, as the date_variable is defined as a string, I dont get the sorting right. How can I re-define the date_variable as a date?
Use the input function to convert the string-value containing a date representation to a date-value that can have a date-style format applied to it that will affect how the date-value is rendered in output and viewers.
The input function requires an informat as an argument. Check the format documentation, which includes an entry for:
DDMMYYw. Informat
Reads date values in the form ddmmyy or dd-mm-yy, where a special character, such as a hyphen (-), period (.), or slash (/), separates the day, month, and year; the year can be either 2 or 4 digits.
Example:
* string values contain date representations;
data have;
input date_from_excel $10.;
cards;
31.01.2019
01.02.2019
15.01.2019
run;
data want;
set have;
date = input(date_from_excel, ddmmyy10.); * convert to SAS date values;
format date ddmmyyd10.; * format to apply when rendering those values;
run;
* sort by SAS date values;
proc sort data=want;
by date;
run;
format date_variable mmddyy10.; does not convert a string to a date. It just sets a format for displaying that field etc.
Essentially I think what you are saying is date_variable is a string that looks like "31.01.2019". If that is the case, you will have to first convert it into a date value:
date_variable_converted = input(date_variable, DDMMYY10.);
You should be now able to sort using date_variable_converted which is a SAS date value.

How to get only first part of the date ('DD') from an entire date?

I've converted a date into string. Now, I want to parse a string to get the DD part from DD-MM-YYYY.
For e.g.
If the date is 03-05-2017 (DD-MM-YYYY) then the goal is to get only first part of the string i.e. 03 (DD).
You've tagged this question as a ServiceNow question, so I assume you're using the ServiceNow GlideDateTime Class to derive the date as a string. If that is correct, did you know that you can actually derive the day of the month directly from the GlideDateTime object? You can use the getDayOfMonth(), getDayOfMonthLocalTime(), or getDayOfMonthUTC().
You could of course, also use String.prototype.indxOf() to get the first hyphen's location, and then return everything up to that location using String.prototype.slice().
Or, if you're certain that the day of the month in the string will contain an initial zero, you can simply .slice() out a new string from index 0 through index 2.
var date = '03-05-2017';
var newDate = date.slice(0, 2);
console.log(newDate); //==>Prints "03".
var alternateNewDate = date.slice(0, date.indexOf('-'));
console.log(alternateNewDate); //==>Prints "03".

Lotus sorting view on orderdate does not work properly

I have created a view in which I also have a column which holds dates. This column can be sorted on ascending and descending. This is my column properties value:
But the problem is that the view does not sort the dates properly:
And here a screenshot of the orderdate field itself:
And here screenshot of the document with the orderdate that is out of order in the view:
Update
Some documents had the orderdate as text instead of date.. I create these documents through a java agent. The field orderdate I fill in like this:
SimpleDateFormat formatterDatumForField=new SimpleDateFormat("dd-MM-yyyy");
docOrder.replaceItemValue("Orderdatum",formatterDatumForField.format(currentDateForField));
But it is saved as text instead of date. Anyone knows why?
Problem was that orderdate field was set by a backend agent and this field was set with a string.
I know saved the current time as a DateTime object and now it works:
DateTime timenow = session.createDateTime("Today");
timenow.setNow();
docOrder.replaceItemValue("Orderdatum", timenow);
It's not clear to me why it's not working for you, but you can brute force it with something like this in the column formula
dateForSure := #TextToTime(OrderDatum);
#Text(#Year(dateForSure)) + "-" + #Text(#Month(dateForSure)) + "-" + #Text(#Day(dateForSure));
Also: your Java code saves a text value because the format() method of SimpleDateFormat returns a StringBuffer. The ReplaceItemValue method generates a text item when its input is a String or StringBuffer. Assuming your form defines OrderDatum as a Time/Date field, you can call Document.ComputeWithForm in your code to force it to convert the text item to a Time/Date. Another method - probably preferable given the potential side-effects of calling ComputeWithForm would be to create a DateTime object in your Java code and pass it to the ReplaceItemValue method instead.
It's because formatterDatumForField.format(currentDateForField) returns a String instead of a date/time value. Assuming that currentDateForField is a date/time value, you should change
SimpleDateFormat formatterDatumForField=new SimpleDateFormat("dd-MM-yyyy");
docOrder.replaceItemValue("Orderdatum",formatterDatumForField.format(currentDateForField));
to
docOrder.replaceItemValue("Orderdatum",currentDateForField);

Date formatting in a grid

I'm trying to display a date column in grid like this: "dd-mm-yyyy". In dbf table, the date is stored in this format: "YYYY-MM-DDThh:mm:ss" in a character field.
The grid is created from this cursor:
select id,beginningDate,endDate,cnp from doc ORDER BY id desc INTO CURSOR myCursor
I wish something like this:
select id,convert(beginningDate, Datetime,"dd-mm-yyyy"),endDate,cnp from doc ORDER BY id desc INTO CURSOR myCursor
Fox doesn't have a builtin function called convert(), nor can it handle your non-standard date/time string format directly.
A quick and dirty way to convert a string foo in the given format ("YYYY-MM-DDThh:mm:ss") to a date/time value is
ctot("^" + chrtran(foo, "T", " "))
The caret marks the input as the locale-independent standard format, which differs from the input format only by having a space instead of a 'T'.
You can extract the date portion from this via the ttod() function, or simply extract only the date portion from the string and convert that:
ctod("^" + left(foo, 10))
Fox's controls - including those in a grid - normally use the configured Windows system format (assuming that set("SYSFORMATS") == "ON"); you can override this by playing with the SET DATE command.
There seems to be no mask-based date formatting option as in most other languages. dtoc() and ttoc() don't take format strings, transform() takes a format string but blithely ignores it for date values.
I am with Tamar on this subject, you should have used a datetime field instead.
Since you are storing it like this anyway, you can 'convert' to datetime using the built-in cast function (or ttod(ctot()) in versions older than VFP9 - in either case you don't need to remove T character):
select id, ;
Cast(Cast("^"+beginningDate as datetime) as date) as beginningDate, ;
endDate,cnp ;
from doc ;
ORDER BY id desc ;
INTO CURSOR myCursor ;
nofilter
In grid or any other textbox control, you can control its display style using DateFormat property. ie:
* assuming it is Columns(2). 11 is DMY
thisform.myGrid.Columns(2).SetAll('DateFormat', 11)

How do I split birt dataset column into multiple rows

My datasource has a column that contains a comma-separated list of numbers.
I want to create a dataset that takes those numbers and turns them into groupings to use in a bar chart.
requirements
numbers will be between 0-17 inclusive
groupings: 0-2,3-5,6-10,11-17
x-axis labels have to be the groupings
y-axis is the percent of rows that contain that grouping
note that because each row can contribute to multiple columns the percentages can add up to > 100%
any help you can offer would be awesome... i'm very new to BIRT and have been stuck on this for a couple days now
Not sure that I understand the requirements exactly, but your basic question "split dataset column into multiple rows" can be solved either using a scripted dataset or with pure SQL (depending on your DB).
Either way, you will need a second dataset (e.g. your data model is master-detail, and in your layout you will need something like
Table/List "Master bound to master DS
Table/List "Detail" bound to detail DS
The detail DS need the comma-separated result column from the master DS as an input parameter of type "String".
Doing this with a scripted dataset is quite easy IFF you understand Javascript AND you understand how scripted datasets work: Create a report variable "myValues" of type object with a default value of null and a second report variable "myValuesIndex" of type integer with a default value of 0.
(Note: this is all untested!)
Create the dataset "detail" as a scripted DS, with one input parameter "csv" of type String and one output parameter "value" of type String.
In the open event of the scripted DS, code:
vars["myValues"] = this.getInputParameterValue("csv").split(",");
vars["myValuesIndex"] = 0;
In the fetch event, code:
var i = vars["myValuesIndex"];
var len = vars["myValues"].length;
if (i < len) {
row["value"] = vars["myValues"][i];
vars["myValuesIndex"] = i+1;
return true;
} else {
return false;
}
For example, for the master DS result row with csv = "1,2,3-4,foo", the detail DS will result in 4 rows with
value = "1"
value = "2"
value = "3-4"
value = "foo"
Using an Oracle DB, this can be done without Javascript. The detail DS (with the same input parameter as above) would then look like:
select t.value as value from table(split(?)) t
For the definition of the split function, see RedFilter's answer on
Is there a function to split a string in PL/SQL?
If you get ORA-22813, you should change the original definition
create or replace type split_tbl as table of varchar2(32767);
to
create or replace type split_tbl as table of varchar2(4000);
as mentioned on https://community.oracle.com/thread/2288603?tstart=0
It's also possible with pure SQL in 11g using regexp_substr (see the same page).
create parameters in the scripted data set. we have to pass or link actual dataset values to scripted dataset parameters through DataSet parameter Binding after assigning the scripted data set to Table.

Resources